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/03 15:16:26 UTC

[camel-k] 02/04: feat(kamelets): enable ServiceAccount for KameletBinding

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

commit 335c0248001de57169d2e3556ce97da9a89bc543
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Fri Feb 3 12:06:37 2023 +0100

    feat(kamelets): enable ServiceAccount for KameletBinding
    
    Closes #3797
---
 .../bases/camel.apache.org_kameletbindings.yaml    |  3 +++
 docs/modules/ROOT/partials/apis/kamelets-crds.adoc |  7 ++++++
 e2e/namespace/install/cli/bind_test.go             |  9 ++++++-
 e2e/support/test_support.go                        | 10 ++++++++
 helm/camel-k/crds/crd-kamelet-binding.yaml         |  3 +++
 pkg/apis/camel/v1alpha1/kamelet_binding_types.go   |  2 ++
 .../camel/v1alpha1/kameletbindingspec.go           | 21 +++++++++++-----
 pkg/cmd/bind.go                                    | 28 +++++++++++++---------
 pkg/cmd/bind_test.go                               | 10 ++++++++
 pkg/controller/kameletbinding/integration.go       |  4 ++++
 10 files changed, 79 insertions(+), 18 deletions(-)

diff --git a/config/crd/bases/camel.apache.org_kameletbindings.yaml b/config/crd/bases/camel.apache.org_kameletbindings.yaml
index cf2213b68..e8f8ae8c5 100644
--- a/config/crd/bases/camel.apache.org_kameletbindings.yaml
+++ b/config/crd/bases/camel.apache.org_kameletbindings.yaml
@@ -7660,6 +7660,9 @@ spec:
                 description: Replicas is the number of desired replicas for the binding
                 format: int32
                 type: integer
+              serviceAccountName:
+                description: Custom SA to use for the binding
+                type: string
               sink:
                 description: Sink is the destination of the integration defined by
                   this binding
diff --git a/docs/modules/ROOT/partials/apis/kamelets-crds.adoc b/docs/modules/ROOT/partials/apis/kamelets-crds.adoc
index 034fedd39..557e5f6ed 100644
--- a/docs/modules/ROOT/partials/apis/kamelets-crds.adoc
+++ b/docs/modules/ROOT/partials/apis/kamelets-crds.adoc
@@ -853,6 +853,13 @@ int32
 
 Replicas is the number of desired replicas for the binding
 
+|`serviceAccountName` +
+string
+|
+
+
+Custom SA to use for the binding
+
 
 |===
 
diff --git a/e2e/namespace/install/cli/bind_test.go b/e2e/namespace/install/cli/bind_test.go
index f2c831873..0e8fb84f4 100644
--- a/e2e/namespace/install/cli/bind_test.go
+++ b/e2e/namespace/install/cli/bind_test.go
@@ -25,7 +25,7 @@ package common
 import (
 	"testing"
 
-	corev1 "k8s.io/api/core/v1"
+	//corev1 "k8s.io/api/core/v1"
 
 	. "github.com/onsi/gomega"
 
@@ -60,5 +60,12 @@ func TestKamelCLIBind(t *testing.T) {
 
 			Expect(Kamel("delete", "--all", "-n", ns).Execute()).To(Succeed())
 		})
+
+		t.Run("bind with custom SA", func(t *testing.T) {
+			Expect(KamelBindWithID(operatorID, ns, "timer:foo", "log:bar", "--service-account", "my-service-account").Execute()).To(Succeed())
+			Eventually(IntegrationSpecSA(ns, "timer-to-log")).Should(Equal("my-service-account"))
+
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).To(Succeed())
+		})
 	})
 }
diff --git a/e2e/support/test_support.go b/e2e/support/test_support.go
index d696e7d40..7bcbb29ad 100644
--- a/e2e/support/test_support.go
+++ b/e2e/support/test_support.go
@@ -970,6 +970,16 @@ func IntegrationSpecProfile(ns string, name string) func() v1.TraitProfile {
 	}
 }
 
+func IntegrationSpecSA(ns string, name string) func() string {
+	return func() string {
+		it := Integration(ns, name)()
+		if it == nil {
+			return ""
+		}
+		return it.Spec.ServiceAccountName
+	}
+}
+
 func IntegrationKit(ns string, name string) func() string {
 	return func() string {
 		it := Integration(ns, name)()
diff --git a/helm/camel-k/crds/crd-kamelet-binding.yaml b/helm/camel-k/crds/crd-kamelet-binding.yaml
index cf2213b68..e8f8ae8c5 100644
--- a/helm/camel-k/crds/crd-kamelet-binding.yaml
+++ b/helm/camel-k/crds/crd-kamelet-binding.yaml
@@ -7660,6 +7660,9 @@ spec:
                 description: Replicas is the number of desired replicas for the binding
                 format: int32
                 type: integer
+              serviceAccountName:
+                description: Custom SA to use for the binding
+                type: string
               sink:
                 description: Sink is the destination of the integration defined by
                   this binding
diff --git a/pkg/apis/camel/v1alpha1/kamelet_binding_types.go b/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
index e5bf003a4..c2d86c542 100644
--- a/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
+++ b/pkg/apis/camel/v1alpha1/kamelet_binding_types.go
@@ -59,6 +59,8 @@ type KameletBindingSpec struct {
 	Steps []Endpoint `json:"steps,omitempty"`
 	// Replicas is the number of desired replicas for the binding
 	Replicas *int32 `json:"replicas,omitempty"`
+	// Custom SA to use for the binding
+	ServiceAccountName string `json:"serviceAccountName,omitempty"`
 }
 
 // Endpoint represents a source/sink external entity (could be any Kubernetes resource or Camel URI)
diff --git a/pkg/client/camel/applyconfiguration/camel/v1alpha1/kameletbindingspec.go b/pkg/client/camel/applyconfiguration/camel/v1alpha1/kameletbindingspec.go
index 23e74bcc0..491566627 100644
--- a/pkg/client/camel/applyconfiguration/camel/v1alpha1/kameletbindingspec.go
+++ b/pkg/client/camel/applyconfiguration/camel/v1alpha1/kameletbindingspec.go
@@ -26,12 +26,13 @@ import (
 // KameletBindingSpecApplyConfiguration represents an declarative configuration of the KameletBindingSpec type for use
 // with apply.
 type KameletBindingSpecApplyConfiguration struct {
-	Integration  *v1.IntegrationSpecApplyConfiguration `json:"integration,omitempty"`
-	Source       *EndpointApplyConfiguration           `json:"source,omitempty"`
-	Sink         *EndpointApplyConfiguration           `json:"sink,omitempty"`
-	ErrorHandler *ErrorHandlerSpecApplyConfiguration   `json:"errorHandler,omitempty"`
-	Steps        []EndpointApplyConfiguration          `json:"steps,omitempty"`
-	Replicas     *int32                                `json:"replicas,omitempty"`
+	Integration        *v1.IntegrationSpecApplyConfiguration `json:"integration,omitempty"`
+	Source             *EndpointApplyConfiguration           `json:"source,omitempty"`
+	Sink               *EndpointApplyConfiguration           `json:"sink,omitempty"`
+	ErrorHandler       *ErrorHandlerSpecApplyConfiguration   `json:"errorHandler,omitempty"`
+	Steps              []EndpointApplyConfiguration          `json:"steps,omitempty"`
+	Replicas           *int32                                `json:"replicas,omitempty"`
+	ServiceAccountName *string                               `json:"serviceAccountName,omitempty"`
 }
 
 // KameletBindingSpecApplyConfiguration constructs an declarative configuration of the KameletBindingSpec type for use with
@@ -92,3 +93,11 @@ func (b *KameletBindingSpecApplyConfiguration) WithReplicas(value int32) *Kamele
 	b.Replicas = &value
 	return b
 }
+
+// WithServiceAccountName sets the ServiceAccountName field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ServiceAccountName field is set to the value of the last call.
+func (b *KameletBindingSpecApplyConfiguration) WithServiceAccountName(value string) *KameletBindingSpecApplyConfiguration {
+	b.ServiceAccountName = &value
+	return b
+}
diff --git a/pkg/cmd/bind.go b/pkg/cmd/bind.go
index 6db6c6cd8..af67cafad 100644
--- a/pkg/cmd/bind.go
+++ b/pkg/cmd/bind.go
@@ -63,6 +63,7 @@ func newCmdBind(rootCmdOptions *RootCmdOptions) (*cobra.Command, *bindCmdOptions
 	cmd.Flags().StringP("operator-id", "x", "camel-k", "Operator id selected to manage this Kamelet binding.")
 	cmd.Flags().StringArray("annotation", nil, "Add an annotation to the Kamelet binding. E.g. \"--annotation my.company=hello\"")
 	cmd.Flags().Bool("force", false, "Force creation of Kamelet binding regardless of potential misconfiguration.")
+	cmd.Flags().String("service-account", "", "The SA to use to run this binding")
 
 	return &cmd, &options
 }
@@ -76,17 +77,18 @@ const (
 
 type bindCmdOptions struct {
 	*RootCmdOptions
-	ErrorHandler string   `mapstructure:"error-handler" yaml:",omitempty"`
-	Name         string   `mapstructure:"name" yaml:",omitempty"`
-	Connects     []string `mapstructure:"connects" yaml:",omitempty"`
-	OutputFormat string   `mapstructure:"output" yaml:",omitempty"`
-	Properties   []string `mapstructure:"properties" yaml:",omitempty"`
-	SkipChecks   bool     `mapstructure:"skip-checks" yaml:",omitempty"`
-	Steps        []string `mapstructure:"steps" yaml:",omitempty"`
-	Traits       []string `mapstructure:"traits" yaml:",omitempty"`
-	OperatorID   string   `mapstructure:"operator-id" yaml:",omitempty"`
-	Annotations  []string `mapstructure:"annotations" yaml:",omitempty"`
-	Force        bool     `mapstructure:"force" yaml:",omitempty"`
+	ErrorHandler   string   `mapstructure:"error-handler" yaml:",omitempty"`
+	Name           string   `mapstructure:"name" yaml:",omitempty"`
+	Connects       []string `mapstructure:"connects" yaml:",omitempty"`
+	OutputFormat   string   `mapstructure:"output" yaml:",omitempty"`
+	Properties     []string `mapstructure:"properties" yaml:",omitempty"`
+	SkipChecks     bool     `mapstructure:"skip-checks" yaml:",omitempty"`
+	Steps          []string `mapstructure:"steps" yaml:",omitempty"`
+	Traits         []string `mapstructure:"traits" yaml:",omitempty"`
+	OperatorID     string   `mapstructure:"operator-id" yaml:",omitempty"`
+	Annotations    []string `mapstructure:"annotations" yaml:",omitempty"`
+	Force          bool     `mapstructure:"force" yaml:",omitempty"`
+	ServiceAccount string   `mapstructure:"service-account" yaml:",omitempty"`
 }
 
 func (o *bindCmdOptions) preRunE(cmd *cobra.Command, args []string) error {
@@ -237,6 +239,10 @@ func (o *bindCmdOptions) run(cmd *cobra.Command, args []string) error {
 		binding.Annotations = make(map[string]string)
 	}
 
+	if o.ServiceAccount != "" {
+		binding.Spec.ServiceAccountName = o.ServiceAccount
+	}
+
 	if !isOfflineCommand(cmd) && o.OperatorID != "" {
 		if err := verifyOperatorID(o.Context, client, o.OperatorID); err != nil {
 			if o.Force {
diff --git a/pkg/cmd/bind_test.go b/pkg/cmd/bind_test.go
index a2729784a..a04436fc1 100644
--- a/pkg/cmd/bind_test.go
+++ b/pkg/cmd/bind_test.go
@@ -235,3 +235,13 @@ spec:
 status: {}
 `, output)
 }
+
+func TestBindServiceAccountName(t *testing.T) {
+	_, bindCmd, _ := initializeBindCmdOptions(t)
+	output, err := test.ExecuteCommand(bindCmd, cmdBind, "timer:foo", "log:bar",
+		"-o", "yaml",
+		"--service-account", "my-service-account")
+
+	assert.Nil(t, err)
+	assert.Contains(t, output, "serviceAccountName: my-service-account")
+}
diff --git a/pkg/controller/kameletbinding/integration.go b/pkg/controller/kameletbinding/integration.go
index e9e1add70..885cdcaa1 100644
--- a/pkg/controller/kameletbinding/integration.go
+++ b/pkg/controller/kameletbinding/integration.go
@@ -93,6 +93,10 @@ func CreateIntegrationFor(ctx context.Context, c client.Client, kameletbinding *
 	}
 	it.Spec.Profile = profile
 
+	if kameletbinding.Spec.ServiceAccountName != "" {
+		it.Spec.ServiceAccountName = kameletbinding.Spec.ServiceAccountName
+	}
+
 	bindingContext := bindings.BindingContext{
 		Ctx:       ctx,
 		Client:    c,