Skip to content

Commit

Permalink
feat(cli): disconnected run and bind
Browse files Browse the repository at this point in the history
If we detect the -o option, then the CLI goes in offline mode, allowing to be used without a K8S cluster.

Closes apache#3021
  • Loading branch information
squakez committed Apr 28, 2022
1 parent edaf8af commit c22d627
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 41 deletions.
40 changes: 26 additions & 14 deletions pkg/cmd/bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,13 @@ func newCmdBind(rootCmdOptions *RootCmdOptions) (*cobra.Command, *bindCmdOptions
RootCmdOptions: rootCmdOptions,
}
cmd := cobra.Command{
Use: "bind [source] [sink] ...",
Short: "Bind Kubernetes resources, such as Kamelets, in an integration flow.",
Long: "Bind Kubernetes resources, such as Kamelets, in an integration flow. Endpoints are expected in the format \"[[apigroup/]version:]kind:[namespace/]name\" or plain Camel URIs.",
PreRunE: decode(&options),
RunE: func(cmd *cobra.Command, args []string) error {
if err := options.validate(cmd, args); err != nil {
return err
}
if err := options.run(cmd, args); err != nil {
fmt.Fprintln(cmd.OutOrStdout(), err.Error())
}

return nil
},
Use: "bind [source] [sink] ...",
Short: "Bind Kubernetes resources, such as Kamelets, in an integration flow.",
Long: "Bind Kubernetes resources, such as Kamelets, in an integration flow. Endpoints are expected in the format \"[[apigroup/]version:]kind:[namespace/]name\" or plain Camel URIs.",
PersistentPreRunE: decode(&options),
PreRunE: options.preRunE,
RunE: options.runE,
Annotations: make(map[string]string),
}

cmd.Flags().StringArrayP("connect", "c", nil, "A ServiceBinding or Provisioned Service that the integration should bind to, specified as [[apigroup/]version:]kind:[namespace/]name")
Expand Down Expand Up @@ -90,6 +83,25 @@ type bindCmdOptions struct {
Traits []string `mapstructure:"traits" yaml:",omitempty"`
}

func (o *bindCmdOptions) preRunE(cmd *cobra.Command, args []string) error {
if o.OutputFormat != "" {
// let the command to work in offline mode
cmd.Annotations[offlineCommandLabel] = "true"
}
return o.RootCmdOptions.preRun(cmd, args)
}

func (o *bindCmdOptions) runE(cmd *cobra.Command, args []string) error {
if err := o.validate(cmd, args); err != nil {
return err
}
if err := o.run(cmd, args); err != nil {
fmt.Fprintln(cmd.OutOrStdout(), err.Error())
}

return nil
}

func (o *bindCmdOptions) validate(cmd *cobra.Command, args []string) error {
if len(args) > 2 {
return errors.New("too many arguments: expected source and sink")
Expand Down
3 changes: 0 additions & 3 deletions pkg/cmd/bind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,6 @@ func initializeBindCmdOptions(t *testing.T) (*bindCmdOptions, *cobra.Command, Ro
func addTestBindCmd(options RootCmdOptions, rootCmd *cobra.Command) *bindCmdOptions {
// add a testing version of bind Command
bindCmd, bindOptions := newCmdBind(&options)
bindCmd.PersistentPreRunE = func(c *cobra.Command, args []string) error {
return nil
}
bindCmd.Args = test.ArbitraryArgs
rootCmd.AddCommand(bindCmd)
return bindOptions
Expand Down
42 changes: 27 additions & 15 deletions pkg/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,15 @@ func newCmdRun(rootCmdOptions *RootCmdOptions) (*cobra.Command, *runCmdOptions)
}

cmd := cobra.Command{
Use: "run [file to run]",
Short: "Run a integration on Kubernetes",
Long: `Deploys and execute a integration pod on Kubernetes.`,
Args: options.validateArgs,
PreRunE: options.decode,
RunE: options.run,
PostRunE: options.postRun,
Use: "run [file to run]",
Short: "Run a integration on Kubernetes",
Long: `Deploys and execute a integration pod on Kubernetes.`,
Args: options.validateArgs,
PersistentPreRunE: options.decode,
PreRunE: options.preRunE,
RunE: options.run,
PostRunE: options.postRun,
Annotations: make(map[string]string),
}

cmd.Flags().String("name", "", "The integration name")
Expand Down Expand Up @@ -154,6 +156,14 @@ type runCmdOptions struct {
Sources []string `mapstructure:"sources" yaml:",omitempty"`
}

func (o *runCmdOptions) preRunE(cmd *cobra.Command, args []string) error {
if o.OutputFormat != "" {
// let the command to work in offline mode
cmd.Annotations[offlineCommandLabel] = "true"
}
return o.RootCmdOptions.preRun(cmd, args)
}

func (o *runCmdOptions) decode(cmd *cobra.Command, args []string) error {
// *************************************************************************
//
Expand Down Expand Up @@ -492,14 +502,16 @@ func (o *runCmdOptions) createOrUpdateIntegration(cmd *cobra.Command, c client.C
}

existing := &v1.Integration{}
err := c.Get(o.Context, ctrl.ObjectKeyFromObject(integration), existing)
switch {
case err == nil:
integration = existing.DeepCopy()
case k8serrors.IsNotFound(err):
existing = nil
default:
return nil, err
if !isOfflineCommand(cmd) {
err := c.Get(o.Context, ctrl.ObjectKeyFromObject(integration), existing)
switch {
case err == nil:
integration = existing.DeepCopy()
case k8serrors.IsNotFound(err):
existing = nil
default:
return nil, err
}
}

var integrationKit *corev1.ObjectReference
Expand Down
15 changes: 6 additions & 9 deletions pkg/cmd/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,6 @@ func addTestRunCmd(options RootCmdOptions, rootCmd *cobra.Command) *runCmdOption
func addTestRunCmdWithOutput(options RootCmdOptions, rootCmd *cobra.Command) *runCmdOptions {
// add a testing version of run Command with output
runCmd, runOptions := newCmdRun(&options)
runCmd.PersistentPreRunE = func(c *cobra.Command, args []string) error {
return nil
}
runCmd.Args = test.ArbitraryArgs
rootCmd.AddCommand(runCmd)
return runOptions
Expand Down Expand Up @@ -604,9 +601,9 @@ func TestOutputYaml(t *testing.T) {
assert.Nil(t, ioutil.WriteFile(tmpFile.Name(), []byte(TestSrcContent), 0o400))
fileName := filepath.Base(tmpFile.Name())

buildCmdOptions, runCmd, _ := initializeRunCmdOptionsWithOutput(t)
runCmdOptions, runCmd, _ := initializeRunCmdOptionsWithOutput(t)
output, err := test.ExecuteCommand(runCmd, cmdRun, tmpFile.Name(), "-o", "yaml")
assert.Equal(t, "yaml", buildCmdOptions.OutputFormat)
assert.Equal(t, "yaml", runCmdOptions.OutputFormat)

assert.Nil(t, err)
assert.Equal(t, fmt.Sprintf(`apiVersion: camel.apache.org/v1
Expand Down Expand Up @@ -635,9 +632,9 @@ func TestTrait(t *testing.T) {
assert.Nil(t, ioutil.WriteFile(tmpFile.Name(), []byte(TestSrcContent), 0o400))
fileName := filepath.Base(tmpFile.Name())

buildCmdOptions, runCmd, _ := initializeRunCmdOptionsWithOutput(t)
runCmdOptions, runCmd, _ := initializeRunCmdOptionsWithOutput(t)
output, err := test.ExecuteCommand(runCmd, cmdRun, tmpFile.Name(), "-o", "yaml", "-t", "mount.configs=configmap:my-cm", "--connect", "my-service-binding")
assert.Equal(t, "yaml", buildCmdOptions.OutputFormat)
assert.Equal(t, "yaml", runCmdOptions.OutputFormat)

assert.Nil(t, err)
assert.Equal(t, fmt.Sprintf(`apiVersion: camel.apache.org/v1
Expand Down Expand Up @@ -674,9 +671,9 @@ func TestMissingTrait(t *testing.T) {
assert.Nil(t, tmpFile.Close())
assert.Nil(t, ioutil.WriteFile(tmpFile.Name(), []byte(TestSrcContent), 0o400))

buildCmdOptions, runCmd, _ := initializeRunCmdOptionsWithOutput(t)
runCmdOptions, runCmd, _ := initializeRunCmdOptionsWithOutput(t)
output, err := test.ExecuteCommand(runCmd, cmdRun, tmpFile.Name(), "-o", "yaml", "-t", "bogus.fail=i-must-fail")
assert.Equal(t, "yaml", buildCmdOptions.OutputFormat)
assert.Equal(t, "yaml", runCmdOptions.OutputFormat)
assert.Equal(t, "Error: bogus.fail=i-must-fail is not a valid trait property\n", output)
assert.NotNil(t, err)
}

0 comments on commit c22d627

Please sign in to comment.