You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pc...@apache.org on 2023/02/13 08:33:14 UTC

[camel-k] branch main updated: feat(cli): promote dry run

This is an automated email from the ASF dual-hosted git repository.

pcongiusti pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git


The following commit(s) were added to refs/heads/main by this push:
     new f0e0ea938 feat(cli): promote dry run
f0e0ea938 is described below

commit f0e0ea938cefb39add1629b02fbd208e3399477d
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Fri Feb 10 17:01:27 2023 +0100

    feat(cli): promote dry run
    
    Close #3888
---
 pkg/cmd/bind.go         |   4 +-
 pkg/cmd/promote.go      |  25 +++++---
 pkg/cmd/promote_test.go | 151 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 171 insertions(+), 9 deletions(-)

diff --git a/pkg/cmd/bind.go b/pkg/cmd/bind.go
index af67cafad..59bce431a 100644
--- a/pkg/cmd/bind.go
+++ b/pkg/cmd/bind.go
@@ -264,7 +264,7 @@ func (o *bindCmdOptions) run(cmd *cobra.Command, args []string) error {
 	}
 
 	if o.OutputFormat != "" {
-		return showOutput(cmd, &binding, o.OutputFormat, client.GetScheme())
+		return showKameletBindingOutput(cmd, &binding, o.OutputFormat, client.GetScheme())
 	}
 
 	replaced, err := kubernetes.ReplaceResource(o.Context, client, &binding)
@@ -280,7 +280,7 @@ func (o *bindCmdOptions) run(cmd *cobra.Command, args []string) error {
 	return nil
 }
 
-func showOutput(cmd *cobra.Command, binding *v1alpha1.KameletBinding, outputFormat string, scheme runtime.ObjectTyper) error {
+func showKameletBindingOutput(cmd *cobra.Command, binding *v1alpha1.KameletBinding, outputFormat string, scheme runtime.ObjectTyper) error {
 	printer := printers.NewTypeSetter(scheme)
 	printer.Delegate = &kubernetes.CLIPrinter{
 		Format: outputFormat,
diff --git a/pkg/cmd/promote.go b/pkg/cmd/promote.go
index 3ebd67bbc..fba185afb 100644
--- a/pkg/cmd/promote.go
+++ b/pkg/cmd/promote.go
@@ -51,7 +51,7 @@ func newCmdPromote(rootCmdOptions *RootCmdOptions) (*cobra.Command, *promoteCmdO
 		RootCmdOptions: rootCmdOptions,
 	}
 	cmd := cobra.Command{
-		Use:     "promote integration --to [namespace] ...",
+		Use:     "promote my-it --to [namespace]",
 		Short:   "Promote an Integration/KameletBinding from an environment to another",
 		Long:    "Promote an Integration/KameletBinding from an environment to another, for example from a Development environment to a Production environment",
 		PreRunE: decode(&options),
@@ -59,13 +59,15 @@ func newCmdPromote(rootCmdOptions *RootCmdOptions) (*cobra.Command, *promoteCmdO
 	}
 
 	cmd.Flags().String("to", "", "The namespace where to promote the Integration")
+	cmd.Flags().StringP("output", "o", "", "Output format. One of: json|yaml")
 
 	return &cmd, &options
 }
 
 type promoteCmdOptions struct {
 	*RootCmdOptions
-	To string `mapstructure:"to" yaml:",omitempty"`
+	To           string `mapstructure:"to" yaml:",omitempty"`
+	OutputFormat string `mapstructure:"output" yaml:",omitempty"`
 }
 
 func (o *promoteCmdOptions) validate(_ *cobra.Command, args []string) error {
@@ -88,7 +90,6 @@ func (o *promoteCmdOptions) run(cmd *cobra.Command, args []string) error {
 	if err != nil {
 		return errors.Wrap(err, "could not retrieve cluster client")
 	}
-
 	opSource, err := operatorInfo(o.Context, c, o.Namespace)
 	if err != nil {
 		return errors.Wrap(err, "could not retrieve info for Camel K operator source")
@@ -123,11 +124,19 @@ func (o *promoteCmdOptions) run(cmd *cobra.Command, args []string) error {
 	if err != nil {
 		return errors.Wrap(err, "could not validate destination resources")
 	}
+
+	// KameletBinding promotion
 	if promoteKameletBinding {
-		// KameletBinding promotion
 		destKameletBinding := o.editKameletBinding(sourceKameletBinding, sourceIntegration)
-
+		// Ensure the destination namespace has access to the source namespace images
+		err = addSystemPullerRoleBinding(o.Context, c, sourceIntegration.Namespace, destKameletBinding.Namespace)
+		if err != nil {
+			return err
+		}
 		replaced, err := o.replaceResource(destKameletBinding)
+		if o.OutputFormat != "" {
+			return showKameletBindingOutput(cmd, destKameletBinding, o.OutputFormat, c.GetScheme())
+		}
 		if !replaced {
 			fmt.Fprintln(cmd.OutOrStdout(), `Promoted Integration "`+name+`" created`)
 		} else {
@@ -135,15 +144,17 @@ func (o *promoteCmdOptions) run(cmd *cobra.Command, args []string) error {
 		}
 		return err
 	}
+
 	// Plain Integration promotion
 	destIntegration := o.editIntegration(sourceIntegration)
-
 	// Ensure the destination namespace has access to the source namespace images
 	err = addSystemPullerRoleBinding(o.Context, c, sourceIntegration.Namespace, destIntegration.Namespace)
 	if err != nil {
 		return err
 	}
-
+	if o.OutputFormat != "" {
+		return showIntegrationOutput(cmd, destIntegration, o.OutputFormat, c.GetScheme())
+	}
 	replaced, err := o.replaceResource(destIntegration)
 	if !replaced {
 		fmt.Fprintln(cmd.OutOrStdout(), `Promoted Integration "`+name+`" created`)
diff --git a/pkg/cmd/promote_test.go b/pkg/cmd/promote_test.go
new file mode 100644
index 000000000..11524aefc
--- /dev/null
+++ b/pkg/cmd/promote_test.go
@@ -0,0 +1,151 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package cmd
+
+import (
+	"fmt"
+	"testing"
+
+	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/platform"
+	"github.com/apache/camel-k/pkg/util/defaults"
+	"github.com/apache/camel-k/pkg/util/test"
+	"github.com/spf13/cobra"
+	"github.com/stretchr/testify/assert"
+	"k8s.io/apimachinery/pkg/runtime"
+)
+
+const cmdPromote = "promote"
+
+// nolint: unparam
+func initializePromoteCmdOptions(t *testing.T, initObjs ...runtime.Object) (*promoteCmdOptions, *cobra.Command, RootCmdOptions) {
+	t.Helper()
+	fakeClient, err := test.NewFakeClient(initObjs...)
+	assert.Nil(t, err)
+	options, rootCmd := kamelTestPreAddCommandInitWithClient(fakeClient)
+	options.Namespace = "default"
+	promoteCmdOptions := addTestPromoteCmd(*options, rootCmd)
+	kamelTestPostAddCommandInit(t, rootCmd)
+
+	return promoteCmdOptions, rootCmd, *options
+}
+
+func addTestPromoteCmd(options RootCmdOptions, rootCmd *cobra.Command) *promoteCmdOptions {
+	promoteCmd, promoteOptions := newCmdPromote(&options)
+	promoteCmd.Args = test.ArbitraryArgs
+	rootCmd.AddCommand(promoteCmd)
+	return promoteOptions
+}
+
+func TestIntegrationNotCompatible(t *testing.T) {
+	srcPlatform := v1.NewIntegrationPlatform("default", platform.DefaultPlatformName)
+	srcPlatform.Status.Version = defaults.Version
+	srcPlatform.Status.Build.RuntimeVersion = defaults.DefaultRuntimeVersion
+	srcPlatform.Status.Phase = v1.IntegrationPlatformPhaseReady
+	dstPlatform := v1.NewIntegrationPlatform("prod-namespace", platform.DefaultPlatformName)
+	dstPlatform.Status.Version = "0.0.1"
+	dstPlatform.Status.Build.RuntimeVersion = "0.0.1"
+	dstPlatform.Status.Phase = v1.IntegrationPlatformPhaseReady
+	defaultIntegration := nominalIntegration("my-it-test")
+
+	promoteCmdOptions, promoteCmd, _ := initializePromoteCmdOptions(t, &srcPlatform, &dstPlatform, &defaultIntegration)
+	_, err := test.ExecuteCommand(promoteCmd, cmdPromote, "my-it-test", "--to", "prod-namespace", "-o", "yaml", "-n", "default")
+	assert.Equal(t, "yaml", promoteCmdOptions.OutputFormat)
+	assert.NotNil(t, err)
+	assert.Equal(t,
+		fmt.Sprintf("could not verify operators compatibility: source (%s) and destination (0.0.1) Camel K operator versions are not compatible", defaults.Version),
+		err.Error(),
+	)
+}
+
+func TestIntegrationDryRun(t *testing.T) {
+	srcPlatform := v1.NewIntegrationPlatform("default", platform.DefaultPlatformName)
+	srcPlatform.Status.Version = defaults.Version
+	srcPlatform.Status.Build.RuntimeVersion = defaults.DefaultRuntimeVersion
+	srcPlatform.Status.Phase = v1.IntegrationPlatformPhaseReady
+	dstPlatform := v1.NewIntegrationPlatform("prod-namespace", platform.DefaultPlatformName)
+	dstPlatform.Status.Version = defaults.Version
+	dstPlatform.Status.Build.RuntimeVersion = defaults.DefaultRuntimeVersion
+	dstPlatform.Status.Phase = v1.IntegrationPlatformPhaseReady
+	defaultIntegration := nominalIntegration("my-it-test")
+
+	promoteCmdOptions, promoteCmd, _ := initializePromoteCmdOptions(t, &srcPlatform, &dstPlatform, &defaultIntegration)
+	output, err := test.ExecuteCommand(promoteCmd, cmdPromote, "my-it-test", "--to", "prod-namespace", "-o", "yaml", "-n", "default")
+	assert.Equal(t, "yaml", promoteCmdOptions.OutputFormat)
+	assert.Nil(t, err)
+	assert.Equal(t, `apiVersion: camel.apache.org/v1
+kind: Integration
+metadata:
+  creationTimestamp: null
+  name: my-it-test
+  namespace: prod-namespace
+spec:
+  traits:
+    container:
+      image: my-special-image
+status: {}
+`, output)
+}
+
+func nominalIntegration(name string) v1.Integration {
+	it := v1.NewIntegration("default", name)
+	it.Status.Phase = v1.IntegrationPhaseRunning
+	it.Status.Image = "my-special-image"
+	return it
+}
+
+func TestKameletBindingDryRun(t *testing.T) {
+	srcPlatform := v1.NewIntegrationPlatform("default", platform.DefaultPlatformName)
+	srcPlatform.Status.Version = defaults.Version
+	srcPlatform.Status.Build.RuntimeVersion = defaults.DefaultRuntimeVersion
+	srcPlatform.Status.Phase = v1.IntegrationPlatformPhaseReady
+	dstPlatform := v1.NewIntegrationPlatform("prod-namespace", platform.DefaultPlatformName)
+	dstPlatform.Status.Version = defaults.Version
+	dstPlatform.Status.Build.RuntimeVersion = defaults.DefaultRuntimeVersion
+	dstPlatform.Status.Phase = v1.IntegrationPlatformPhaseReady
+	defaultKB := nominalKameletBinding("my-kb-test")
+	defaultIntegration := nominalIntegration("my-kb-test")
+
+	promoteCmdOptions, promoteCmd, _ := initializePromoteCmdOptions(t, &srcPlatform, &dstPlatform, &defaultKB, &defaultIntegration)
+	output, err := test.ExecuteCommand(promoteCmd, cmdPromote, "my-kb-test", "--to", "prod-namespace", "-o", "yaml", "-n", "default")
+	assert.Equal(t, "yaml", promoteCmdOptions.OutputFormat)
+	assert.Nil(t, err)
+	assert.Equal(t, `apiVersion: camel.apache.org/v1alpha1
+kind: KameletBinding
+metadata:
+  creationTimestamp: null
+  name: my-kb-test
+  namespace: prod-namespace
+  resourceVersion: "1"
+spec:
+  integration:
+    traits:
+      container:
+        image: my-special-image
+  sink: {}
+  source: {}
+status: {}
+`, output)
+}
+
+func nominalKameletBinding(name string) v1alpha1.KameletBinding {
+	kb := v1alpha1.NewKameletBinding("default", name)
+	kb.Status.Phase = v1alpha1.KameletBindingPhaseReady
+	return kb
+}