This is an automated email from the ASF dual-hosted git repository. nferraro pushed a commit to branch release-1.3.x in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit d14636936793275487362beb1fa7007d2e5cf1e0 Author: nicolaferraro <ni.ferr...@gmail.com> AuthorDate: Thu Jan 21 11:08:26 2021 +0100 Fix #1928: use "id" property in kamelet binding for adding specific configuration --- .../kamelet-autoload-specific.feature | 23 +++++++++++ .../kamelet-autoload.feature | 21 ++++++++++ .../kamelet-binding-autoload/secret-default.yaml | 10 +++++ .../kamelet-binding-autoload/secret-specific.yaml | 11 +++++ .../timer-source.kamelet.yaml | 48 ++++++++++++++++++++++ .../kamelet-binding-autoload/yaks-config.yaml | 29 +++++++++++++ pkg/apis/camel/v1alpha1/kamelet_types.go | 7 +++- pkg/apis/camel/v1alpha1/kamelet_types_support.go | 10 +++++ pkg/kamelet/initialize.go | 18 +++++++- pkg/util/bindings/bindings_test.go | 14 +++++++ pkg/util/bindings/kamelet.go | 6 +++ 11 files changed, 193 insertions(+), 4 deletions(-) diff --git a/e2e/yaks/common/kamelet-binding-autoload/kamelet-autoload-specific.feature b/e2e/yaks/common/kamelet-binding-autoload/kamelet-autoload-specific.feature new file mode 100644 index 0000000..ddba9f0 --- /dev/null +++ b/e2e/yaks/common/kamelet-binding-autoload/kamelet-autoload-specific.feature @@ -0,0 +1,23 @@ +Feature: Camel K can load specific secrets for Kamelets + + Background: + Given Disable auto removal of Kamelet resources + Given Disable auto removal of Kubernetes resources + Given Camel-K resource polling configuration + | maxAttempts | 20 | + | delayBetweenAttempts | 1000 | + + Scenario: KameletBinding can load specific settings for Kamelet + Given create Kubernetes service stub-service-2 with target port 8081 + And bind Kamelet timer-source to uri http://stub-service-2.${YAKS_NAMESPACE}.svc.cluster.local/specific + And KameletBinding source properties + | id | specific | + When create KameletBinding binding-specific + Then KameletBinding binding-specific should be available + + Scenario: Verify specific binding + Given HTTP server "stub-service-2" + And HTTP server timeout is 60000 ms + Then expect HTTP request body: specific + And receive POST /specific + And delete KameletBinding binding-specific diff --git a/e2e/yaks/common/kamelet-binding-autoload/kamelet-autoload.feature b/e2e/yaks/common/kamelet-binding-autoload/kamelet-autoload.feature new file mode 100644 index 0000000..c92a126 --- /dev/null +++ b/e2e/yaks/common/kamelet-binding-autoload/kamelet-autoload.feature @@ -0,0 +1,21 @@ +Feature: Camel K can load default secrets for Kamelets + + Background: + Given Disable auto removal of Kamelet resources + Given Disable auto removal of Kubernetes resources + Given Camel-K resource polling configuration + | maxAttempts | 20 | + | delayBetweenAttempts | 1000 | + + Scenario: KameletBinding can load default settings for Kamelet + Given create Kubernetes service stub-service with target port 8080 + And bind Kamelet timer-source to uri http://stub-service.${YAKS_NAMESPACE}.svc.cluster.local/default + When create KameletBinding binding + Then KameletBinding binding should be available + + Scenario: Verify default binding + Given HTTP server "stub-service" + And HTTP server timeout is 60000 ms + Then expect HTTP request body: default + And receive POST /default + And delete KameletBinding binding diff --git a/e2e/yaks/common/kamelet-binding-autoload/secret-default.yaml b/e2e/yaks/common/kamelet-binding-autoload/secret-default.yaml new file mode 100644 index 0000000..edb12ce --- /dev/null +++ b/e2e/yaks/common/kamelet-binding-autoload/secret-default.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Secret +metadata: + name: secret-default + labels: + camel.apache.org/kamelet: timer-source +type: Opaque +data: + # camel.kamelet.timer-source.message=default + application.properties: Y2FtZWwua2FtZWxldC50aW1lci1zb3VyY2UubWVzc2FnZT1kZWZhdWx0Cg== diff --git a/e2e/yaks/common/kamelet-binding-autoload/secret-specific.yaml b/e2e/yaks/common/kamelet-binding-autoload/secret-specific.yaml new file mode 100644 index 0000000..b5cbfcb --- /dev/null +++ b/e2e/yaks/common/kamelet-binding-autoload/secret-specific.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Secret +metadata: + name: secret-specific + labels: + camel.apache.org/kamelet: timer-source + camel.apache.org/kamelet.configuration: specific +type: Opaque +data: + # camel.kamelet.timer-source.specific.message=specific + application.properties: Y2FtZWwua2FtZWxldC50aW1lci1zb3VyY2Uuc3BlY2lmaWMubWVzc2FnZT1zcGVjaWZpYwo= diff --git a/e2e/yaks/common/kamelet-binding-autoload/timer-source.kamelet.yaml b/e2e/yaks/common/kamelet-binding-autoload/timer-source.kamelet.yaml new file mode 100644 index 0000000..eb74334 --- /dev/null +++ b/e2e/yaks/common/kamelet-binding-autoload/timer-source.kamelet.yaml @@ -0,0 +1,48 @@ +# --------------------------------------------------------------------------- +# 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. +# --------------------------------------------------------------------------- + +apiVersion: camel.apache.org/v1alpha1 +kind: Kamelet +metadata: + name: timer-source + labels: + camel.apache.org/kamelet.type: "source" +spec: + definition: + title: "Timer" + description: "Produces periodic events with a custom payload" + required: + - message + properties: + period: + title: Period + description: The time interval between two events + type: integer + default: 1000 + message: + title: Message + description: The message to generate + type: string + flow: + from: + uri: timer:tick + parameters: + period: "{{period}}" + steps: + - set-body: + constant: "{{message}}" + - to: "kamelet:sink" diff --git a/e2e/yaks/common/kamelet-binding-autoload/yaks-config.yaml b/e2e/yaks/common/kamelet-binding-autoload/yaks-config.yaml new file mode 100644 index 0000000..a71f271 --- /dev/null +++ b/e2e/yaks/common/kamelet-binding-autoload/yaks-config.yaml @@ -0,0 +1,29 @@ +# --------------------------------------------------------------------------- +# 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. +# --------------------------------------------------------------------------- + +config: + namespace: + temporary: true +pre: +- name: installation + run: | + kamel install -n $YAKS_NAMESPACE + + kubectl apply -f secret-default.yaml -n $YAKS_NAMESPACE + kubectl apply -f secret-specific.yaml -n $YAKS_NAMESPACE + + kubectl apply -f timer-source.kamelet.yaml -n $YAKS_NAMESPACE diff --git a/pkg/apis/camel/v1alpha1/kamelet_types.go b/pkg/apis/camel/v1alpha1/kamelet_types.go index 7a1cef7..987593d 100644 --- a/pkg/apis/camel/v1alpha1/kamelet_types.go +++ b/pkg/apis/camel/v1alpha1/kamelet_types.go @@ -29,6 +29,7 @@ const ( var ( reservedKameletNames = map[string]bool{"source": true, "sink": true} + KameletIDProperty = "id" ) // KameletSpec defines the desired state of Kamelet @@ -94,8 +95,10 @@ const ( ) const ( - // KameletConditionIllegalName -- - KameletConditionIllegalName string = "IllegalName" + // KameletConditionReasonInvalidName -- + KameletConditionReasonInvalidName string = "InvalidName" + // KameletConditionReasonInvalidProperty -- + KameletConditionReasonInvalidProperty string = "InvalidProperty" ) type KameletPhase string diff --git a/pkg/apis/camel/v1alpha1/kamelet_types_support.go b/pkg/apis/camel/v1alpha1/kamelet_types_support.go index 2aa2c85..9e6f540 100644 --- a/pkg/apis/camel/v1alpha1/kamelet_types_support.go +++ b/pkg/apis/camel/v1alpha1/kamelet_types_support.go @@ -140,3 +140,13 @@ func (in *KameletStatus) RemoveCondition(condType KameletConditionType) { func ValidKameletName(name string) bool { return !reservedKameletNames[name] } + +func ValidKameletProperties(kamelet *Kamelet) bool { + if kamelet == nil || kamelet.Spec.Definition == nil || kamelet.Spec.Definition.Properties == nil { + return true + } + if _, idPresent := kamelet.Spec.Definition.Properties[KameletIDProperty]; idPresent { + return false + } + return true +} diff --git a/pkg/kamelet/initialize.go b/pkg/kamelet/initialize.go index 755c9fc..7fd4373 100644 --- a/pkg/kamelet/initialize.go +++ b/pkg/kamelet/initialize.go @@ -30,14 +30,28 @@ import ( func Initialize(kamelet *v1alpha1.Kamelet) (*v1alpha1.Kamelet, error) { target := kamelet.DeepCopy() + ok := true if !v1alpha1.ValidKameletName(kamelet.Name) { - target.Status.Phase = v1alpha1.KameletPhaseError + ok = false target.Status.SetCondition( v1alpha1.KameletConditionReady, corev1.ConditionFalse, - v1alpha1.KameletConditionIllegalName, + v1alpha1.KameletConditionReasonInvalidName, fmt.Sprintf("Kamelet name %q is reserved", kamelet.Name), ) + } + if !v1alpha1.ValidKameletProperties(kamelet) { + ok = false + target.Status.SetCondition( + v1alpha1.KameletConditionReady, + corev1.ConditionFalse, + v1alpha1.KameletConditionReasonInvalidProperty, + fmt.Sprintf("Kamelet property %q is reserved and cannot be part of the schema", v1alpha1.KameletIDProperty), + ) + } + + if !ok { + target.Status.Phase = v1alpha1.KameletPhaseError } else { target.Status.Phase = v1alpha1.KameletPhaseReady target.Status.SetCondition( diff --git a/pkg/util/bindings/bindings_test.go b/pkg/util/bindings/bindings_test.go index 72e8ce5..55d005f 100644 --- a/pkg/util/bindings/bindings_test.go +++ b/pkg/util/bindings/bindings_test.go @@ -137,6 +137,20 @@ func TestBindings(t *testing.T) { uri: "kamelet:mykamelet?encodedkey%3F=encoded%3Dval&mymessage=myval", }, { + endpoint: v1alpha1.Endpoint{ + Ref: &corev1.ObjectReference{ + Kind: "Kamelet", + APIVersion: "camel.apache.org/v1any1", + Name: "mykamelet", + }, + Properties: asEndpointProperties(map[string]string{ + "id": "myid?", + "mymessage": "myval", + }), + }, + uri: "kamelet:mykamelet/myid%3F?mymessage=myval", + }, + { endpointType: v1alpha1.EndpointTypeSink, endpoint: v1alpha1.Endpoint{ URI: asStringPointer("https://myurl/hey"), diff --git a/pkg/util/bindings/kamelet.go b/pkg/util/bindings/kamelet.go index 48fc456..089a7d4 100644 --- a/pkg/util/bindings/kamelet.go +++ b/pkg/util/bindings/kamelet.go @@ -50,6 +50,12 @@ func (k KameletBindingProvider) Translate(ctx BindingContext, endpointType v1alp if err != nil { return nil, err } + + if id, ok := props[v1alpha1.KameletIDProperty]; ok && id != "" { + delete(props, v1alpha1.KameletIDProperty) + kameletURI = fmt.Sprintf("%s/%s", kameletURI, url.PathEscape(id)) + } + kameletURI = uri.AppendParameters(kameletURI, props) return &Binding{