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 <[email protected]> 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,
