Skip to content

Commit

Permalink
feat: support kamelet version in Pipe
Browse files Browse the repository at this point in the history
  • Loading branch information
squakez committed Sep 2, 2024
1 parent 8b0981d commit f9f159e
Show file tree
Hide file tree
Showing 12 changed files with 112 additions and 23 deletions.
2 changes: 1 addition & 1 deletion docs/modules/ROOT/pages/kamelets/kamelets-dev.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ spec:

NOTE: make sure the overall content fits into 1 MiB, which is the storage limit for a Custom Resource.

This is a way to handle multiple version on Kubernetes and may not be supported out of the box by Camel core. If the Integration will require specifically to use `kamelet:my-timer-source?version=v2`, then, the operator will mount properly the specification on the running application.
This is a way to handle multiple version on Kubernetes and may not be supported out of the box by Camel core. If the Integration will require specifically to use `kamelet:my-timer-source?kameletVersion=v2`, then, the operator will mount properly the specification on the running application.

== Kamelet data types

Expand Down
2 changes: 1 addition & 1 deletion docs/modules/ROOT/pages/kamelets/kamelets-user.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ Kamelets provided in a catalog are generally meant to work with a given runtime
.kamlet-namedconfig-route.yaml
----
- from:
uri: "timer:tick?version=v2"
uri: "timer:tick?kameletVersion=v2"
steps:
- to: "log:info"
----
Expand Down
19 changes: 19 additions & 0 deletions e2e/common/traits/files/kamelet-it-main.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
# camel-k: language=yaml

# ---------------------------------------------------------------------------
# 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.
# ---------------------------------------------------------------------------

- from:
uri: "kamelet:my-timer-source"
steps:
Expand Down
19 changes: 19 additions & 0 deletions e2e/common/traits/files/kamelet-it-v1.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
# camel-k: language=yaml

# ---------------------------------------------------------------------------
# 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.
# ---------------------------------------------------------------------------

- from:
uri: "kamelet:my-timer-source?version=v1"
steps:
Expand Down
17 changes: 17 additions & 0 deletions e2e/common/traits/files/my-timer-source.kamelet.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
# ---------------------------------------------------------------------------
# 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/v1
kind: Kamelet
metadata:
Expand Down
2 changes: 2 additions & 0 deletions pkg/apis/camel/v1/kamelet_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ var (
reservedKameletNames = map[string]bool{"source": true, "sink": true}
// KameletIDProperty used to identify.
KameletIDProperty = "id"
// KameletVersionProperty used to specify the version to use.
KameletVersionProperty = "kameletVersion"
)

// +genclient
Expand Down
16 changes: 9 additions & 7 deletions pkg/trait/kamelets.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ const (
kameletMountPointAnnotation = "camel.apache.org/kamelet.mount-point"
)

var kameletVersionProperty = fmt.Sprintf("?%s=", v1.KameletVersionProperty)

type kameletsTrait struct {
BaseTrait
traitv1.KameletsTrait `property:",squash"`
Expand Down Expand Up @@ -181,8 +183,8 @@ func (t *kameletsTrait) addKamelets(e *Environment) error {
return err
}
kb := newKameletBundle()
for version, kamelet := range kamelets {
if err := t.addKameletAsSource(e, kamelet, version); err != nil {
for _, kamelet := range kamelets {
if err := t.addKameletAsSource(e, kamelet); err != nil {
return err
}
// Adding dependencies from Kamelets
Expand Down Expand Up @@ -218,7 +220,7 @@ func (t *kameletsTrait) addKamelets(e *Environment) error {
// This func will add a Kamelet as a generated Integration source. The source included here is going to be used in order to parse the Kamelet
// for any component or capability (ie, rest) which is included in the Kamelet spec itself. However, the generated source is marked as coming `FromKamelet`.
// When mounting the sources, these generated sources won't be mounted as sources but as Kamelet instead.
func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet *v1.Kamelet, version string) error {
func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet *v1.Kamelet) error {
sources := make([]v1.SourceSpec, 0)

if kamelet.Spec.Template != nil {
Expand Down Expand Up @@ -281,8 +283,8 @@ func getKameletKey(item string, withVersion bool) string {
if strings.Contains(i, "/") {
i = strings.SplitN(i, "/", 2)[0]
}
if strings.Contains(i, "?version=") {
versionedKamelet := strings.SplitN(i, "?version=", 2)
if strings.Contains(i, kameletVersionProperty) {
versionedKamelet := strings.SplitN(i, kameletVersionProperty, 2)
if withVersion {
i = fmt.Sprintf("%s-%s", versionedKamelet[0], versionedKamelet[1])
} else {
Expand All @@ -293,8 +295,8 @@ func getKameletKey(item string, withVersion bool) string {
}

func getKameletVersion(item string) string {
if strings.Contains(item, "?version=") {
versionedKamelet := strings.SplitN(item, "?version=", 2)
if strings.Contains(item, fmt.Sprintf("?%s=", v1.KameletVersionProperty)) {
versionedKamelet := strings.SplitN(item, kameletVersionProperty, 2)
return versionedKamelet[1]
}
return ""
Expand Down
6 changes: 3 additions & 3 deletions pkg/trait/kamelets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func TestConfigurationWithKamelets(t *testing.T) {
uri: kamelet:c1
steps:
- to: kamelet:c2
- to: kamelet:c3?version=v1
- to: kamelet:c3?kameletVersion=v1
- to: telegram:bots
- to: kamelet://c0?prop=x
- to: kamelet://complex-.-.-1a?prop=x&prop2
Expand Down Expand Up @@ -222,7 +222,7 @@ func TestNonYAMLKameletLookup(t *testing.T) {
func TestMultipleKamelets(t *testing.T) {
trait, environment := createKameletsTestEnvironment(`
- from:
uri: kamelet:timer?version=v1
uri: kamelet:timer?kameletVersion=v1
steps:
- to: kamelet:logger
`, &v1.Kamelet{
Expand Down Expand Up @@ -310,7 +310,7 @@ func TestMultipleKamelets(t *testing.T) {
require.NoError(t, err)
assert.True(t, enabled)
assert.Nil(t, condition)
assert.Equal(t, "logger,timer?version=v1", trait.List)
assert.Equal(t, "logger,timer?kameletVersion=v1", trait.List)
assert.Equal(t, []string{"logger", "timer"}, trait.getKameletKeys(false))
assert.Equal(t, []string{"logger", "timer-v1"}, trait.getKameletKeys(true))

Expand Down
18 changes: 18 additions & 0 deletions pkg/util/bindings/bindings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,24 @@ func TestBindings(t *testing.T) {
"camel.kamelet.mykamelet.sink.mymessage": "myval",
},
},
{
endpointType: v1.EndpointTypeSink,
endpoint: v1.Endpoint{
Ref: &corev1.ObjectReference{
Kind: "Kamelet",
APIVersion: "camel.apache.org/v1any1",
Name: "mykamelet",
},
Properties: asEndpointProperties(map[string]string{
"mymessage": "myval",
"kameletVersion": "v1",
}),
},
uri: "kamelet:mykamelet/sink?kameletVersion=v1",
props: map[string]string{
"camel.kamelet.mykamelet.sink.mymessage": "myval",
},
},
{
endpoint: v1.Endpoint{
Ref: &corev1.ObjectReference{
Expand Down
26 changes: 18 additions & 8 deletions pkg/util/bindings/kamelet.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ func (k BindingConverter) ID() string {
}

// Translate --.
//
//nolint:dupl
func (k BindingConverter) Translate(ctx BindingContext, endpointCtx EndpointContext, e v1.Endpoint) (*Binding, error) {
if e.Ref == nil {
// works only on refs
Expand Down Expand Up @@ -71,6 +69,12 @@ func (k BindingConverter) Translate(ctx BindingContext, endpointCtx EndpointCont
} else {
id = endpointCtx.GenerateID()
}
version, versionPresent := props[v1.KameletVersionProperty]
if versionPresent {
delete(props, v1.KameletVersionProperty)
}

kameletTranslated := getKameletName(kameletName, id, version)

binding := Binding{}
binding.ApplicationProperties = make(map[string]string)
Expand All @@ -97,7 +101,7 @@ func (k BindingConverter) Translate(ctx BindingContext, endpointCtx EndpointCont

steps = append(steps, map[string]interface{}{
"kamelet": map[string]interface{}{
"name": fmt.Sprintf("%s/%s", kameletName, url.PathEscape(id)),
"name": kameletTranslated,
},
})

Expand Down Expand Up @@ -126,7 +130,7 @@ func (k BindingConverter) Translate(ctx BindingContext, endpointCtx EndpointCont
}
}

binding.URI = fmt.Sprintf("kamelet:%s/%s", kameletName, url.PathEscape(id))
binding.URI = fmt.Sprintf("kamelet:%s", kameletTranslated)
case v1.EndpointTypeSink:
if in, applicationProperties := k.DataTypeStep(e, id, v1.TypeSlotIn, dataTypeActionKamelet); in != nil {
binding.Step = in
Expand All @@ -135,14 +139,22 @@ func (k BindingConverter) Translate(ctx BindingContext, endpointCtx EndpointCont
}
}

binding.URI = fmt.Sprintf("kamelet:%s/%s", kameletName, url.PathEscape(id))
binding.URI = fmt.Sprintf("kamelet:%s", kameletTranslated)
default:
binding.URI = fmt.Sprintf("kamelet:%s/%s", kameletName, url.PathEscape(id))
binding.URI = fmt.Sprintf("kamelet:%s", kameletTranslated)
}

return &binding, nil
}

func getKameletName(name, id, version string) string {
kamelet := fmt.Sprintf("%s/%s", name, url.PathEscape(id))
if version != "" {
kamelet = fmt.Sprintf("%s?%s=%s", kamelet, v1.KameletVersionProperty, version)
}
return kamelet
}

// DataTypeStep --.
func (k BindingConverter) DataTypeStep(e v1.Endpoint, id string, typeSlot v1.TypeSlot, dataTypeActionKamelet string) (map[string]interface{}, map[string]string) {
if e.DataTypes == nil {
Expand Down Expand Up @@ -193,8 +205,6 @@ func (k V1alpha1BindingConverter) ID() string {

// Translate -- .
// Deprecated.
//
//nolint:dupl
func (k V1alpha1BindingConverter) Translate(ctx V1alpha1BindingContext, endpointCtx V1alpha1EndpointContext, e v1alpha1.Endpoint) (*Binding, error) {
if e.Ref == nil {
// works only on refs
Expand Down
4 changes: 3 additions & 1 deletion pkg/util/source/kamelet.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ package source
import (
"fmt"
"regexp"

v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
)

var kameletNameRegexp = regexp.MustCompile("kamelet:(?://)?([a-z0-9-.]+(/[a-z0-9-.]+)?)(?:$|[^a-z0-9-.].*)")
var kameletVersionRegexp = regexp.MustCompile("version=([a-z0-9-.]+)")
var kameletVersionRegexp = regexp.MustCompile(v1.KameletVersionProperty + "=([a-z0-9-.]+)")

func ExtractKamelets(uris []string) []string {
var kamelets []string
Expand Down
4 changes: 2 additions & 2 deletions pkg/util/source/kamelet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ func TestExtractKamelets(t *testing.T) {
assert.Equal(t, "my-test", ExtractKamelet("kamelet:my-test?"))
assert.Equal(t, "my-test", ExtractKamelet("kamelet:my-test?option=1"))
assert.Equal(t, "my-test", ExtractKamelet("kamelet:my-test?option=1&opt2=2"))
assert.Equal(t, "my-test?version=v1", ExtractKamelet("kamelet:my-test?option=1&opt2=2&version=v1"))
assert.Equal(t, "my-test?version=v1", ExtractKamelet("kamelet:my-test?version=v1"))
assert.Equal(t, "my-test?kameletVersion=v1", ExtractKamelet("kamelet:my-test?option=1&opt2=2&kameletVersion=v1"))
assert.Equal(t, "my-test?kameletVersion=v1", ExtractKamelet("kamelet:my-test?kameletVersion=v1"))
}

0 comments on commit f9f159e

Please sign in to comment.