This is an automated email from the ASF dual-hosted git repository. nferraro pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit 29c883f97142293d6f50eb62100b4d3607ed398c Author: nicolaferraro <ni.ferr...@gmail.com> AuthorDate: Mon Dec 20 18:18:37 2021 +0100 Fix #1107: add tests for kamelet binding and replicas --- addons/keda/keda_test.go | 191 ++++++++++++++++++++- .../bases/camel-k.clusterserviceversion.yaml | 8 +- pkg/controller/kameletbinding/common.go | 2 +- pkg/controller/kameletbinding/initialize.go | 2 +- pkg/controller/kameletbinding/monitor.go | 2 +- pkg/resources/resources.go | 4 +- pkg/trait/dependencies_test.go | 2 +- pkg/trait/init.go | 2 +- pkg/trait/trait_register.go | 2 +- 9 files changed, 196 insertions(+), 19 deletions(-) diff --git a/addons/keda/keda_test.go b/addons/keda/keda_test.go index 083a231..ae49b4a 100644 --- a/addons/keda/keda_test.go +++ b/addons/keda/keda_test.go @@ -19,11 +19,13 @@ package keda import ( "context" + "encoding/json" "testing" "github.com/apache/camel-k/addons/keda/duck/v1alpha1" camelv1 "github.com/apache/camel-k/pkg/apis/camel/v1" camelv1alpha1 "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" + "github.com/apache/camel-k/pkg/controller/kameletbinding" "github.com/apache/camel-k/pkg/trait" "github.com/apache/camel-k/pkg/util/camel" "github.com/apache/camel-k/pkg/util/kubernetes" @@ -33,6 +35,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" ) var ( @@ -205,6 +208,156 @@ func TestKameletAutoDetection(t *testing.T) { assert.Contains(t, secret.StringData, "cc") } +func TestKameletBindingAutoDetection(t *testing.T) { + keda, _ := NewKedaTrait().(*kedaTrait) + keda.Enabled = &testingTrue + logEndpoint := "log:info" + klb := camelv1alpha1.KameletBinding{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "my-binding", + }, + Spec: camelv1alpha1.KameletBindingSpec{ + Source: camelv1alpha1.Endpoint{ + Ref: &corev1.ObjectReference{ + Kind: "Kamelet", + APIVersion: camelv1alpha1.SchemeGroupVersion.String(), + Name: "my-kamelet", + }, + Properties: asEndpointProperties(map[string]string{ + "a": "v1", + "b": "v2", + "c": "v3", + }), + }, + Sink: camelv1alpha1.Endpoint{ + URI: &logEndpoint, + }, + }, + } + + env := createBasicTestEnvironment( + &camelv1alpha1.Kamelet{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "my-kamelet", + Annotations: map[string]string{ + "camel.apache.org/keda.type": "my-scaler", + }, + }, + Spec: camelv1alpha1.KameletSpec{ + Definition: &camelv1alpha1.JSONSchemaProps{ + Properties: map[string]camelv1alpha1.JSONSchemaProp{ + "a": camelv1alpha1.JSONSchemaProp{ + XDescriptors: []string{ + "urn:keda:metadata:a", + }, + }, + "b": camelv1alpha1.JSONSchemaProp{ + XDescriptors: []string{ + "urn:keda:metadata:bb", + }, + }, + "c": camelv1alpha1.JSONSchemaProp{ + XDescriptors: []string{ + "urn:keda:authentication:cc", + }, + }, + }, + }, + }, + }, + &klb, + &camelv1.IntegrationPlatform{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "camel-k", + }, + Spec: camelv1.IntegrationPlatformSpec{ + Cluster: camelv1.IntegrationPlatformClusterKubernetes, + Profile: camelv1.TraitProfileKubernetes, + }, + Status: camelv1.IntegrationPlatformStatus{ + Phase: camelv1.IntegrationPlatformPhaseReady, + }, + }) + + it, err := kameletbinding.CreateIntegrationFor(env.Ctx, env.Client, &klb) + assert.NoError(t, err) + assert.NotNil(t, it) + env.Integration = it + + it.Status.Phase = camelv1.IntegrationPhaseInitialization + init := trait.NewInitTrait() + ok, err := init.Configure(env) + assert.NoError(t, err) + assert.True(t, ok) + assert.NoError(t, init.Apply(env)) + + it.Status.Phase = camelv1.IntegrationPhaseDeploying + res, err := keda.Configure(env) + assert.NoError(t, err) + assert.True(t, res) + assert.NoError(t, keda.Apply(env)) + so := getScaledObject(env) + assert.NotNil(t, so) + assert.Len(t, so.Spec.Triggers, 1) + assert.Equal(t, "my-scaler", so.Spec.Triggers[0].Type) + assert.Equal(t, map[string]string{ + "a": "v1", + "bb": "v2", + }, so.Spec.Triggers[0].Metadata) + triggerAuth := getTriggerAuthentication(env) + assert.NotNil(t, triggerAuth) + assert.Equal(t, so.Spec.Triggers[0].AuthenticationRef.Name, triggerAuth.Name) + assert.Len(t, triggerAuth.Spec.SecretTargetRef, 1) + assert.Equal(t, "cc", triggerAuth.Spec.SecretTargetRef[0].Key) + assert.Equal(t, "cc", triggerAuth.Spec.SecretTargetRef[0].Parameter) + secretName := triggerAuth.Spec.SecretTargetRef[0].Name + secret := getSecret(env) + assert.NotNil(t, secret) + assert.Equal(t, secretName, secret.Name) + assert.Len(t, secret.StringData, 1) + assert.Contains(t, secret.StringData, "cc") +} + +func TestHackReplicas(t *testing.T) { + keda, _ := NewKedaTrait().(*kedaTrait) + keda.Enabled = &testingTrue + keda.Auto = &testingFalse + keda.Triggers = append(keda.Triggers, kedaTrigger{ + Type: "custom", + Metadata: map[string]string{ + "a": "b", + }, + }) + keda.HackControllerReplicas = &testingTrue + env := createBasicTestEnvironment( + &camelv1.Integration{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "my-it", + }, + Status: camelv1.IntegrationStatus{ + Phase: camelv1.IntegrationPhaseInitialization, + }, + }, + ) + + res, err := keda.Configure(env) + assert.NoError(t, err) + assert.True(t, res) + assert.NoError(t, keda.Apply(env)) + it := camelv1.Integration{} + key := client.ObjectKey{ + Namespace: "test", + Name: "my-it", + } + assert.NoError(t, env.Client.Get(env.Ctx, key, &it)) + assert.NotNil(t, it.Spec.Replicas) + assert.Equal(t, int32(1), *it.Spec.Replicas) +} + func getScaledObject(e *trait.Environment) *v1alpha1.ScaledObject { var res *v1alpha1.ScaledObject for _, o := range e.Resources.Items() { @@ -268,6 +421,25 @@ func createBasicTestEnvironment(resources ...runtime.Object) *trait.Environment } } + var pl *camelv1.IntegrationPlatform + for _, res := range resources { + if platform, ok := res.(*camelv1.IntegrationPlatform); ok { + pl = platform + } + } + if pl == nil { + pl = &camelv1.IntegrationPlatform{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "camel-k", + }, + Spec: camelv1.IntegrationPlatformSpec{ + Cluster: camelv1.IntegrationPlatformClusterKubernetes, + Profile: camelv1.TraitProfileKubernetes, + }, + } + } + return &trait.Environment{ Catalog: trait.NewCatalog(nil), Ctx: context.Background(), @@ -281,15 +453,18 @@ func createBasicTestEnvironment(resources ...runtime.Object) *trait.Environment }, }, }, - Platform: &camelv1.IntegrationPlatform{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", - }, - Spec: camelv1.IntegrationPlatformSpec{ - Cluster: camelv1.IntegrationPlatformClusterKubernetes, - }, - }, + Platform: pl, Resources: kubernetes.NewCollection(), ApplicationProperties: make(map[string]string), } } + +func asEndpointProperties(props map[string]string) *camelv1alpha1.EndpointProperties { + serialized, err := json.Marshal(props) + if err != nil { + panic(err) + } + return &camelv1alpha1.EndpointProperties{ + RawMessage: serialized, + } +} diff --git a/config/manifests/bases/camel-k.clusterserviceversion.yaml b/config/manifests/bases/camel-k.clusterserviceversion.yaml index 03b7414..ed06b13 100644 --- a/config/manifests/bases/camel-k.clusterserviceversion.yaml +++ b/config/manifests/bases/camel-k.clusterserviceversion.yaml @@ -23,8 +23,9 @@ metadata: categories: Integration & Delivery certified: "false" containerImage: docker.io/apache/camel-k:1.8.0-SNAPSHOT - createdAt: 2021-05-03T07:48:00Z - description: Apache Camel K is a lightweight integration platform, born on Kubernetes, with serverless superpowers. + createdAt: 2021-12-20T16:11:27Z + description: Apache Camel K is a lightweight integration platform, born on Kubernetes, + with serverless superpowers. operators.operatorframework.io/builder: operator-sdk-v1.3.0 operators.operatorframework.io/internal-objects: '["builds.camel.apache.org","integrationkits.camel.apache.org","camelcatalogs.camel.apache.org"]' operators.operatorframework.io/project_layout: go.kubebuilder.io/v2 @@ -51,7 +52,8 @@ spec: kind: IntegrationKit name: integrationkits.camel.apache.org version: v1 - - description: IntegrationPlatform is the Schema for the integrationplatforms API + - description: IntegrationPlatform is the Schema for the integrationplatforms + API displayName: Integration Platform kind: IntegrationPlatform name: integrationplatforms.camel.apache.org diff --git a/pkg/controller/kameletbinding/common.go b/pkg/controller/kameletbinding/common.go index ea7e3d0..cf9ec2b 100644 --- a/pkg/controller/kameletbinding/common.go +++ b/pkg/controller/kameletbinding/common.go @@ -41,7 +41,7 @@ var ( endpointTypeSinkContext = bindings.EndpointContext{Type: v1alpha1.EndpointTypeSink} ) -func createIntegrationFor(ctx context.Context, c client.Client, kameletbinding *v1alpha1.KameletBinding) (*v1.Integration, error) { +func CreateIntegrationFor(ctx context.Context, c client.Client, kameletbinding *v1alpha1.KameletBinding) (*v1.Integration, error) { controller := true blockOwnerDeletion := true annotations := util.CopyMap(kameletbinding.Annotations) diff --git a/pkg/controller/kameletbinding/initialize.go b/pkg/controller/kameletbinding/initialize.go index c257825..d65656a 100644 --- a/pkg/controller/kameletbinding/initialize.go +++ b/pkg/controller/kameletbinding/initialize.go @@ -50,7 +50,7 @@ func (action *initializeAction) CanHandle(kameletbinding *v1alpha1.KameletBindin } func (action *initializeAction) Handle(ctx context.Context, kameletbinding *v1alpha1.KameletBinding) (*v1alpha1.KameletBinding, error) { - it, err := createIntegrationFor(ctx, action.client, kameletbinding) + it, err := CreateIntegrationFor(ctx, action.client, kameletbinding) if err != nil { return nil, err } diff --git a/pkg/controller/kameletbinding/monitor.go b/pkg/controller/kameletbinding/monitor.go index dcba3b2..e92c35a 100644 --- a/pkg/controller/kameletbinding/monitor.go +++ b/pkg/controller/kameletbinding/monitor.go @@ -70,7 +70,7 @@ func (action *monitorAction) Handle(ctx context.Context, kameletbinding *v1alpha } // Check if the integration needs to be changed - expected, err := createIntegrationFor(ctx, action.client, kameletbinding) + expected, err := CreateIntegrationFor(ctx, action.client, kameletbinding) if err != nil { return nil, err } diff --git a/pkg/resources/resources.go b/pkg/resources/resources.go index c753ccb..414e4d8 100644 --- a/pkg/resources/resources.go +++ b/pkg/resources/resources.go @@ -555,9 +555,9 @@ var assets = func() http.FileSystem { "/traits.yaml": &vfsgen۰CompressedFileInfo{ name: "traits.yaml", modTime: time.Time{}, - uncompressedSize: 49398, + uncompressedSize: 49560, - compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xfd\x73\x5b\xb9\x91\xe0\xef\xf3\x57\xa0\xb4\x57\x65\x49\x45\x52\x9e\xc9\x26\x3b\xa7\xbb\xd9\x94\xc6\x76\x12\xcd\xf8\x43\x67\x3b\xb3\x97\x9a\x9b\x0a\xc1\xf7\x9a\x24\xcc\x47\xe0\x05\xc0\x93\xcc\xdc\xde\xff\x7e\x85\xee\xc6\xc7\x7b\x24\x25\xca\xb6\x66\xa3\xad\xdd\x54\xed\x58\xd2\x03\xd0\x68\x34\xfa\xbb\x1b\xde\x4a\xe5\xdd\xf9\x57\x63\xa1\xe5\x1a\xce\x85\x9c\xcf\x95\x56\x7e\xf3\x95\x10\x6d\x23\xfd\xdc\xd8\xf5\xb9\x [...] + compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xfd\x73\x5b\xb9\x91\xe0\xef\xf3\x57\xa0\xb4\x57\x65\x49\x45\x52\x9e\xc9\x26\x3b\xa7\xbb\xd9\x94\xc6\x76\x12\xcd\xf8\x43\x67\x3b\xb3\x97\x9a\x9b\x0a\xc1\xf7\x9a\x24\xcc\x47\xe0\x05\xc0\x93\xcc\xdc\xde\xff\x7e\x85\xee\xc6\xc7\x7b\x24\x25\xca\xb6\x66\xa3\xad\xdd\x54\xed\x58\xd2\x03\xd0\x68\x34\xfa\xbb\x1b\xde\x4a\xe5\xdd\xf9\x57\x63\xa1\xe5\x1a\xce\x85\x9c\xcf\x95\x56\x7e\xf3\x95\x10\x6d\x23\xfd\xdc\xd8\xf5\xb9\x [...] }, } fs["/"].(*vfsgen۰DirInfo).entries = []os.FileInfo{ diff --git a/pkg/trait/dependencies_test.go b/pkg/trait/dependencies_test.go index d0e8eda..d5cb612 100644 --- a/pkg/trait/dependencies_test.go +++ b/pkg/trait/dependencies_test.go @@ -175,7 +175,7 @@ func TestIntegrationAutoGeneratedDeps(t *testing.T) { }, } - for _, trait := range []Trait{newInitTrait(), newDependenciesTrait()} { + for _, trait := range []Trait{NewInitTrait(), newDependenciesTrait()} { enabled, err := trait.Configure(e) assert.Nil(t, err) assert.True(t, enabled) diff --git a/pkg/trait/init.go b/pkg/trait/init.go index 3cf8472..14f0ca6 100644 --- a/pkg/trait/init.go +++ b/pkg/trait/init.go @@ -33,7 +33,7 @@ type initTrait struct { BaseTrait `property:",squash"` } -func newInitTrait() Trait { +func NewInitTrait() Trait { return &initTrait{ BaseTrait: NewBaseTrait("init", 1), } diff --git a/pkg/trait/trait_register.go b/pkg/trait/trait_register.go index 4f2a6d1..df8245c 100644 --- a/pkg/trait/trait_register.go +++ b/pkg/trait/trait_register.go @@ -32,7 +32,7 @@ func init() { AddToTraits(newErrorHandlerTrait) AddToTraits(newGarbageCollectorTrait) AddToTraits(newHealthTrait) - AddToTraits(newInitTrait) + AddToTraits(NewInitTrait) AddToTraits(newIngressTrait) AddToTraits(newIstioTrait) AddToTraits(newJolokiaTrait)