Skip to content
This repository has been archived by the owner on Mar 13, 2021. It is now read-only.

Move subscription management to new subscription subcommand #775

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions cmd/commands/cobra.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ func AtPosition(i int, validator PositionalArg) cobra.PositionalArgs {
}
}

func OptionalAtPosition(i int, validator PositionalArg) cobra.PositionalArgs {
return func(cmd *cobra.Command, args []string) error {
if len(args) > i {
return validator(cmd, args[i])
}
return nil
}
}

// KubernetesValidation turns a kubernetes-style validation function into a PositionalArg
func KubernetesValidation(k8s func(string) []string) PositionalArg {
return func(cmd *cobra.Command, arg string) error {
Expand Down
19 changes: 19 additions & 0 deletions cmd/commands/cobra_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
package commands_test

import (
"errors"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/projectriff/riff/cmd/commands"
. "github.com/spf13/cobra"
)

var _ = Describe("The cobra extensions", func() {
Expand Down Expand Up @@ -53,5 +55,22 @@ var _ = Describe("The cobra extensions", func() {

})

It("should not fail if an optional argument to validate is not provided", func() {
command := &Command{
Use: "some-command",
Args: commands.ArgValidationConjunction(
MaximumNArgs(1),
commands.OptionalAtPosition(1, func(_ *Command, _ string) error {
return errors.New("should not be called")
}),
),
RunE: func(cmd *Command, args []string) error {
return nil
},
}

Expect(command.Execute()).NotTo(HaveOccurred())
})

})
})
87 changes: 2 additions & 85 deletions cmd/commands/function.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package commands
import (
"fmt"

"github.com/knative/eventing/pkg/apis/channels/v1alpha1"
"github.com/projectriff/riff/pkg/core"
"github.com/spf13/cobra"
)
Expand All @@ -43,11 +42,7 @@ func Function() *cobra.Command {
}

func FunctionCreate(fcTool *core.Client) *cobra.Command {

createInputChannelOptions := core.CreateChannelOptions{}
createOutputChannelOptions := core.CreateChannelOptions{}
createFunctionOptions := core.CreateFunctionOptions{}
createSubscriptionOptions := core.CreateSubscriptionOptions{}

invokers := map[string]string{
"command": "https://github.com/projectriff/command-function-invoker/raw/v0.0.7/command-invoker.yaml",
Expand All @@ -57,7 +52,7 @@ func FunctionCreate(fcTool *core.Client) *cobra.Command {

command := &cobra.Command{
Use: "create",
Short: "Create a new function resource, with optional input and output channels",
Short: "Create a new function resource",
Long: "Create a new function resource from the content of the provided Git repo/revision.\n" +
"\nThe INVOKER arg defines the language invoker that is added to the function code in the build step. The resulting image is then used to create a Knative Service (`service.serving.knative.dev`) instance of the name specified for the function." +
"\nFrom then on you can use the sub-commands for the `service` command to interact with the service created for the function.\n\n" +
Expand All @@ -66,21 +61,13 @@ func FunctionCreate(fcTool *core.Client) *cobra.Command {
` + envFromLongDesc + `
`,
Example: ` riff function create node square --git-repo https://github.com/acme/square --image acme/square --namespace joseph-ns
riff function create java tweets-logger --git-repo https://github.com/acme/tweets --image acme/tweets-logger:1.0.0 --input tweets --bus kafka`,
riff function create java tweets-logger --git-repo https://github.com/acme/tweets --image acme/tweets-logger:1.0.0`,
Args: ArgValidationConjunction(
cobra.ExactArgs(functionCreateNumberOfArgs),
AtPosition(functionCreateInvokerIndex, ValidName()),
AtPosition(functionCreateFunctionNameIndex, ValidName()),
),
PreRunE: FlagsValidatorAsCobraRunE(
FlagsValidationConjunction(
FlagsDependency(Set("input"), exactlyOneOfBusOrClusterBus),
FlagsDependency(NotSet("input"), NoneOf("bus", "cluster-bus")),
FlagsDependency(NotSet("input"), NoneOf("output")),
),
),
RunE: func(cmd *cobra.Command, args []string) error {

fnName := args[functionCreateFunctionNameIndex]
invoker := args[functionCreateInvokerIndex]
invokerURL, exists := invokers[invoker]
Expand All @@ -95,43 +82,11 @@ func FunctionCreate(fcTool *core.Client) *cobra.Command {
return err
}

var c *v1alpha1.Channel
var subscr *v1alpha1.Subscription
if createInputChannelOptions.Name != "" {
c, err = (*fcTool).CreateChannel(createInputChannelOptions)
if err != nil {
return err
}

if createOutputChannelOptions.Name != "" {
c, err = (*fcTool).CreateChannel(createOutputChannelOptions)
if err != nil {
return err
}
}
createSubscriptionOptions.Name = subscriptionNameFromService(fnName)
createSubscriptionOptions.Subscriber = subscriberNameFromService(fnName)
subscr, err = (*fcTool).CreateSubscription(createSubscriptionOptions)
if err != nil {
return err
}
}

if createFunctionOptions.DryRun {
marshaller := NewMarshaller(cmd.OutOrStdout())
if err = marshaller.Marshal(f); err != nil {
return err
}
if c != nil {
if err = marshaller.Marshal(c); err != nil {
return err
}
}
if subscr != nil {
if err = marshaller.Marshal(subscr); err != nil {
return err
}
}
} else {
printSuccessfulCompletion(cmd)
if !createFunctionOptions.Verbose && !createFunctionOptions.Wait {
Expand All @@ -152,55 +107,17 @@ func FunctionCreate(fcTool *core.Client) *cobra.Command {
command.Flags().VarP(
BroadcastStringValue("",
&createFunctionOptions.Namespace,
&createInputChannelOptions.Namespace,
&createOutputChannelOptions.Namespace,
&createSubscriptionOptions.Namespace,
),
"namespace", "n", "the `namespace` of the subscription, channel, and function",
)

command.Flags().VarP(
BroadcastStringValue("",
&createInputChannelOptions.Name,
&createSubscriptionOptions.Channel,
),
"input", "i", "name of the function's input `channel`, if any",
)

command.Flags().VarP(
BroadcastStringValue("",
&createOutputChannelOptions.Name,
&createSubscriptionOptions.ReplyTo,
),
"output", "o", "name of the function's output `channel`, if any",
)

command.Flags().VarPF(
BroadcastBoolValue(false,
&createFunctionOptions.DryRun,
&createInputChannelOptions.DryRun,
&createOutputChannelOptions.DryRun,
&createSubscriptionOptions.DryRun,
),
"dry-run", "", dryRunUsage,
).NoOptDefVal = "true"

command.Flags().Var(
BroadcastStringValue("",
&createInputChannelOptions.Bus,
&createOutputChannelOptions.Bus,
),
"bus", busUsage,
)

command.Flags().Var(
BroadcastStringValue("",
&createInputChannelOptions.ClusterBus,
&createOutputChannelOptions.ClusterBus,
),
"cluster-bus", clusterBusUsage,
)

command.Flags().StringVar(&createFunctionOptions.Image, "image", "", "the name of the image to build; must be a writable `repository/image[:tag]` with credentials configured")
command.MarkFlagRequired("image")
command.Flags().StringVar(&createFunctionOptions.GitRepo, "git-repo", "", "the `URL` for a git repository hosting the function code")
Expand Down
72 changes: 1 addition & 71 deletions cmd/commands/function_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (

"strings"

v1alpha12 "github.com/knative/eventing/pkg/apis/channels/v1alpha1"
"github.com/knative/serving/pkg/apis/serving/v1alpha1"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
Expand Down Expand Up @@ -65,12 +64,6 @@ var _ = Describe("The riff function create command", func() {
Expect(err).To(MatchError(ContainSubstring("git-repo")))
Expect(err).To(MatchError(ContainSubstring("image")))
})
It("should fail when input is set w/o bus or cluster-bus", func() {
fc.SetArgs([]string{"node", "square", "--image", "foo/bar", "--git-repo", "https://github.com/repo",
"--input", "i"})
err := fc.Execute()
Expect(err).To(MatchError("when --input is set, at least one of --bus, --cluster-bus must be set"))
})
})

Context("when given suitable args and flags", func() {
Expand Down Expand Up @@ -132,39 +125,8 @@ var _ = Describe("The riff function create command", func() {
err := fc.Execute()
Expect(err).NotTo(HaveOccurred())
})
It("should create channel/subscription when asked to", func() {
fc.SetArgs([]string{"node", "square", "--image", "foo/bar", "--git-repo", "https://github.com/repo",
"--input", "my-channel", "--bus", "kafka"})

functionOptions := core.CreateFunctionOptions{
GitRepo: "https://github.com/repo",
GitRevision: "master",
InvokerURL: "https://github.com/projectriff/node-function-invoker/raw/v0.0.8/node-invoker.yaml",
}
functionOptions.Name = "square"
functionOptions.Image = "foo/bar"
functionOptions.Env = []string{}
functionOptions.EnvFrom = []string{}

channelOptions := core.CreateChannelOptions{
Name: "my-channel",
Bus: "kafka",
}
subscriptionOptions := core.CreateSubscriptionOptions{
Name: "square",
Channel: "my-channel",
Subscriber: "square",
}

asMock.On("CreateFunction", functionOptions, mock.Anything).Return(nil, nil)
asMock.On("CreateChannel", channelOptions).Return(nil, nil)
asMock.On("CreateSubscription", subscriptionOptions).Return(nil, nil)
err := fc.Execute()
Expect(err).NotTo(HaveOccurred())
})
It("should print when --dry-run is set", func() {
fc.SetArgs([]string{"node", "square", "--image", "foo/bar", "--git-repo", "https://github.com/repo",
"--input", "my-channel", "--bus", "kafka", "--dry-run"})
fc.SetArgs([]string{"node", "square", "--image", "foo/bar", "--git-repo", "https://github.com/repo", "--dry-run"})

functionOptions := core.CreateFunctionOptions{
GitRepo: "https://github.com/repo",
Expand All @@ -177,27 +139,9 @@ var _ = Describe("The riff function create command", func() {
functionOptions.EnvFrom = []string{}
functionOptions.DryRun = true

channelOptions := core.CreateChannelOptions{
Name: "my-channel",
Bus: "kafka",
DryRun: true,
}
subscriptionOptions := core.CreateSubscriptionOptions{
Name: "square",
Channel: "my-channel",
Subscriber: "square",
DryRun: true,
}

f := v1alpha1.Service{}
f.Name = "square"
c := v1alpha12.Channel{}
c.Name = "my-channel"
s := v1alpha12.Subscription{}
s.Name = "square"
asMock.On("CreateFunction", functionOptions, mock.Anything).Return(&f, nil)
asMock.On("CreateChannel", channelOptions).Return(&c, nil)
asMock.On("CreateSubscription", subscriptionOptions).Return(&s, nil)

stdout := &strings.Builder{}
fc.SetOutput(stdout)
Expand Down Expand Up @@ -268,20 +212,6 @@ const fnCreateDryRun = `metadata:
spec: {}
status: {}
---
metadata:
creationTimestamp: null
name: my-channel
spec: {}
status: {}
---
metadata:
creationTimestamp: null
name: square
spec:
channel: ""
subscriber: ""
status: {}
---
`

var _ = Describe("The riff function build command", func() {
Expand Down
Loading