Repository: apache/camel-k
Pull request #4215 (2023-04-03 07:27:51)

[Backport 1.12.x] fix(cmd): rebuild KameletBindings
<!-- Description -->




<!--
Enter your extended release note in the below block. If the PR requires
additional action from users switching to the new release, include the string
"action required". If no release note is required, write "NONE". 

You can (optionally) mark this PR with labels "kind/bug" or "kind/feature" to make sure
the text is added to the right section of the release notes. 
-->

**Release Note**
```release-note
fix(cmd): rebuild KameletBindings
```



Patch:
diff --git a/pkg/cmd/rebuild.go b/pkg/cmd/rebuild.go
index 9c402c23a..bfe7059f2 100644
--- a/pkg/cmd/rebuild.go
+++ b/pkg/cmd/rebuild.go
@@ -22,11 +22,15 @@ import (
 
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
+	"k8s.io/apimachinery/pkg/labels"
+	"k8s.io/apimachinery/pkg/selection"
 
 	k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
 
 	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/client"
+	"github.com/apache/camel-k/pkg/util/kubernetes"
 )
 
 func newCmdRebuild(rootCmdOptions *RootCmdOptions) (*cobra.Command, *rebuildCmdOptions) {
@@ -68,11 +72,80 @@ func (o *rebuildCmdOptions) validate(args []string) error {
 }
 
 func (o *rebuildCmdOptions) run(cmd *cobra.Command, args []string) error {
+	errKlbs := o.rebuildKameletBindingType(cmd, args)
+	errIts := o.rebuildIntegrationType(cmd, args)
+
+	if errIts != nil && errKlbs != nil {
+		return errors.Wrap(errIts, errKlbs.Error())
+	}
+
+	return nil
+}
+
+func (o *rebuildCmdOptions) rebuildKameletBindingType(cmd *cobra.Command, args []string) error {
 	c, err := o.GetCmdClient()
 	if err != nil {
 		return err
 	}
+	var kameletBindings []v1alpha1.KameletBinding
+	if o.RebuildAll {
+		if kameletBindings, err = o.listAllKameletBindings(c); err != nil {
+			return err
+		}
+	} else if len(args) > 0 {
+		if kameletBindings, err = o.getKameletBindings(c, args); err != nil {
+			return err
+		}
+	}
+
+	if err = o.rebuildKameletBindings(c, kameletBindings); err != nil {
+		return err
+	}
+
+	fmt.Fprintln(cmd.OutOrStdout(), len(kameletBindings), "kamelet bindings have been rebuilt")
+	return nil
+}
+
+func (o *rebuildCmdOptions) listAllKameletBindings(c client.Client) ([]v1alpha1.KameletBinding, error) {
+	list := v1alpha1.NewKameletBindingList()
+	if err := c.List(o.Context, &list, k8sclient.InNamespace(o.Namespace)); err != nil {
+		return nil, errors.Wrap(err, fmt.Sprintf("could not retrieve kamelet bindings from namespace %s", o.Namespace))
+	}
+	return list.Items, nil
+}
 
+func (o *rebuildCmdOptions) getKameletBindings(c client.Client, names []string) ([]v1alpha1.KameletBinding, error) {
+	klbs := make([]v1alpha1.KameletBinding, 0, len(names))
+	for _, n := range names {
+		klb := v1alpha1.NewKameletBinding(o.Namespace, n)
+		key := k8sclient.ObjectKey{
+			Name:      n,
+			Namespace: o.Namespace,
+		}
+		if err := c.Get(o.Context, key, &klb); err != nil {
+			return nil, errors.Wrap(err, fmt.Sprintf("could not find kamelet binding %s in namespace %s", klb.Name, o.Namespace))
+		}
+		klbs = append(klbs, klb)
+	}
+	return klbs, nil
+}
+
+func (o *rebuildCmdOptions) rebuildKameletBindings(c k8sclient.StatusClient, kameletbindings []v1alpha1.KameletBinding) error {
+	for _, i := range kameletbindings {
+		klb := i
+		klb.Status = v1alpha1.KameletBindingStatus{}
+		if err := c.Status().Update(o.Context, &klb); err != nil {
+			return errors.Wrap(err, fmt.Sprintf("could not rebuild kamelet binding %s in namespace %s", klb.Name, o.Namespace))
+		}
+	}
+	return nil
+}
+
+func (o *rebuildCmdOptions) rebuildIntegrationType(cmd *cobra.Command, args []string) error {
+	c, err := o.GetCmdClient()
+	if err != nil {
+		return err
+	}
 	var integrations []v1.Integration
 	if o.RebuildAll {
 		if integrations, err = o.listAllIntegrations(c); err != nil {
@@ -94,7 +167,19 @@ func (o *rebuildCmdOptions) run(cmd *cobra.Command, args []string) error {
 
 func (o *rebuildCmdOptions) listAllIntegrations(c client.Client) ([]v1.Integration, error) {
 	list := v1.NewIntegrationList()
-	if err := c.List(o.Context, &list, k8sclient.InNamespace(o.Namespace)); err != nil {
+	// Integrations controlled by KameletBindings are not included
+	excludeItsFromKlbs, err := labels.NewRequirement(kubernetes.CamelCreatorLabelKind, selection.NotEquals, []string{
+		"KameletBinding",
+	})
+	if err != nil {
+		return list.Items, err
+	}
+	if err := c.List(o.Context, &list,
+		k8sclient.InNamespace(o.Namespace),
+		k8sclient.MatchingLabelsSelector{
+			Selector: labels.NewSelector().Add(*excludeItsFromKlbs),
+		},
+	); err != nil {
 		return nil, errors.Wrap(err, fmt.Sprintf("could not retrieve integrations from namespace %s", o.Namespace))
 	}
 	return list.Items, nil
@@ -111,7 +196,10 @@ func (o *rebuildCmdOptions) getIntegrations(c client.Client, names []string) ([]
 		if err := c.Get(o.Context, key, &it); err != nil {
 			return nil, errors.Wrap(err, fmt.Sprintf("could not find integration %s in namespace %s", it.Name, o.Namespace))
 		}
-		ints = append(ints, it)
+		// Integrations controlled by KameletBindings are not included
+		if it.Labels[kubernetes.CamelCreatorLabelKind] != "KameletBinding" {
+			ints = append(ints, it)
+		}
 	}
 	return ints, nil
 }
diff --git a/script/get_catalog.sh b/script/get_catalog.sh
index 0a4b5ded1..85d4d7b33 100755
--- a/script/get_catalog.sh
+++ b/script/get_catalog.sh
@@ -15,7 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-set -ex
+set -e
 
 location=$(dirname $0)
 rootdir=$location/../


Test patch:
diff --git a/pkg/cmd/rebuild_test.go b/pkg/cmd/rebuild_test.go
index e6e0c95a4..91b8dc054 100644
--- a/pkg/cmd/rebuild_test.go
+++ b/pkg/cmd/rebuild_test.go
@@ -20,18 +20,22 @@ package cmd
 import (
 	"testing"
 
+	"github.com/apache/camel-k/pkg/util/kubernetes"
 	"github.com/apache/camel-k/pkg/util/test"
 	"github.com/spf13/cobra"
 	"github.com/stretchr/testify/assert"
+	"k8s.io/apimachinery/pkg/runtime"
 )
 
 const cmdRebuild = "rebuild"
 
 // nolint: unparam
-func initializeRebuildCmdOptions(t *testing.T) (*rebuildCmdOptions, *cobra.Command, RootCmdOptions) {
+func initializeRebuildOptions(t *testing.T, initObjs ...runtime.Object) (*rebuildCmdOptions, *cobra.Command, RootCmdOptions) {
 	t.Helper()
-
-	options, rootCmd := kamelTestPreAddCommandInit()
+	fakeClient, err := test.NewFakeClient(initObjs...)
+	assert.Nil(t, err)
+	options, rootCmd := kamelTestPreAddCommandInitWithClient(fakeClient)
+	options.Namespace = "default"
 	rebuildCmdOptions := addTestRebuildCmd(*options, rootCmd)
 	kamelTestPostAddCommandInit(t, rootCmd)
 
@@ -39,28 +43,82 @@ func initializeRebuildCmdOptions(t *testing.T) (*rebuildCmdOptions, *cobra.Comma
 }
 
 func addTestRebuildCmd(options RootCmdOptions, rootCmd *cobra.Command) *rebuildCmdOptions {
-	// add a testing version of rebuild Command
 	rebuildCmd, rebuildOptions := newCmdRebuild(&options)
-	rebuildCmd.RunE = func(c *cobra.Command, args []string) error {
-		return nil
-	}
-	rebuildCmd.PostRunE = func(c *cobra.Command, args []string) error {
-		return nil
-	}
 	rebuildCmd.Args = test.ArbitraryArgs
 	rootCmd.AddCommand(rebuildCmd)
 	return rebuildOptions
 }
 
 func TestRebuildNonExistingFlag(t *testing.T) {
-	_, rootCmd, _ := initializeRebuildCmdOptions(t)
+	_, rootCmd, _ := initializeRebuildOptions(t)
 	_, err := test.ExecuteCommand(rootCmd, cmdRebuild, "--nonExistingFlag")
 	assert.NotNil(t, err)
 }
 
 func TestRebuildAllFlag(t *testing.T) {
-	rebuildCmdOptions, rootCmd, _ := initializeRebuildCmdOptions(t)
+	rebuildCmdOptions, rootCmd, _ := initializeRebuildOptions(t)
 	_, err := test.ExecuteCommand(rootCmd, cmdRebuild, "--all")
 	assert.Nil(t, err)
 	assert.Equal(t, true, rebuildCmdOptions.RebuildAll)
 }
+
+func TestRebuildAllKameletBindingsAndIntegrations(t *testing.T) {
+	defaultIntegration := nominalIntegration("my-it-test")
+	defaultKB := nominalKameletBinding("my-kb-test-rebuild")
+	itGeneratedByKlb := nominalIntegration("my-kb-test-rebuild")
+	itGeneratedByKlb.Labels = map[string]string{
+		kubernetes.CamelCreatorLabelKind: "KameletBinding",
+	}
+
+	_, rebuildCmd, _ := initializeRebuildOptions(t, &defaultIntegration, &defaultKB, &itGeneratedByKlb)
+	output, err := test.ExecuteCommand(rebuildCmd, cmdRebuild, "--all")
+	assert.Nil(t, err)
+	assert.Contains(t, output, "1 kamelet bindings have been rebuilt")
+	assert.Contains(t, output, "1 integrations have been rebuilt")
+}
+
+func TestRebuildNone(t *testing.T) {
+	defaultIntegration := nominalIntegration("my-it-test")
+	defaultKB := nominalKameletBinding("my-kb-test")
+	itGeneratedByKlb := nominalIntegration("my-kb-test")
+	itGeneratedByKlb.Labels = map[string]string{
+		kubernetes.CamelCreatorLabelKind: "KameletBinding",
+	}
+
+	_, rebuildCmd, _ := initializeRebuildOptions(t, &defaultIntegration, &defaultKB, &itGeneratedByKlb)
+	output, err := test.ExecuteCommand(rebuildCmd, cmdRebuild, "my-missing")
+	assert.NotNil(t, err)
+	assert.NotContains(t, output, "have been rebuilt")
+	assert.Contains(t, output, "could not find kamelet binding my-missing in namespace default")
+	assert.Contains(t, output, "could not find integration my-missing in namespace default")
+}
+
+func TestRebuildKameletBindingOnly(t *testing.T) {
+	defaultIntegration := nominalIntegration("my-it-test")
+	defaultKB := nominalKameletBinding("my-kb-test")
+	itGeneratedByKlb := nominalIntegration("my-kb-test")
+	itGeneratedByKlb.Labels = map[string]string{
+		kubernetes.CamelCreatorLabelKind: "KameletBinding",
+	}
+
+	_, rebuildCmd, _ := initializeRebuildOptions(t, &defaultIntegration, &defaultKB, &itGeneratedByKlb)
+	output, err := test.ExecuteCommand(rebuildCmd, cmdRebuild, "my-kb-test")
+	assert.Nil(t, err)
+	assert.Contains(t, output, "1 kamelet bindings have been rebuilt")
+	assert.NotContains(t, output, "1 integrations have been rebuilt")
+}
+
+func TestRebuildIntegrationOnly(t *testing.T) {
+	defaultIntegration := nominalIntegration("my-it-test")
+	defaultKB := nominalKameletBinding("my-kb-test")
+	itGeneratedByKlb := nominalIntegration("my-kb-test")
+	itGeneratedByKlb.Labels = map[string]string{
+		kubernetes.CamelCreatorLabelKind: "KameletBinding",
+	}
+
+	_, rebuildCmd, _ := initializeRebuildOptions(t, &defaultIntegration, &defaultKB, &itGeneratedByKlb)
+	output, err := test.ExecuteCommand(rebuildCmd, cmdRebuild, "my-it-test")
+	assert.Nil(t, err)
+	assert.NotContains(t, output, "1 kamelet bindings have been rebuilt")
+	assert.Contains(t, output, "1 integrations have been rebuilt")
+}