This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 69a6947eb28c8c24425f347df8006ef626acd43b
Author: Nicola Ferraro <[email protected]>
AuthorDate: Fri Jul 3 11:45:05 2020 +0200

    kamelets: support automatic configuration
---
 pkg/apis/camel/v1/integration_types_support.go |  16 +++
 pkg/trait/kamelets.go                          |  94 ++++++++++++++--
 pkg/trait/kamelets_test.go                     | 150 ++++++++++++++++++++++++-
 pkg/util/test/client.go                        |  19 +++-
 4 files changed, 264 insertions(+), 15 deletions(-)

diff --git a/pkg/apis/camel/v1/integration_types_support.go 
b/pkg/apis/camel/v1/integration_types_support.go
index dd848f0..2e807d3 100644
--- a/pkg/apis/camel/v1/integration_types_support.go
+++ b/pkg/apis/camel/v1/integration_types_support.go
@@ -156,6 +156,22 @@ func (in *IntegrationStatus) 
AddOrReplaceGeneratedSources(sources ...SourceSpec)
        in.GeneratedSources = append(in.GeneratedSources, newSources...)
 }
 
+// AddConfigurationsIfMissing --
+func (in *IntegrationStatus) AddConfigurationsIfMissing(configurations 
...ConfigurationSpec) {
+       for _, config := range configurations {
+               alreadyPresent := false
+               for _, r := range in.Configuration {
+                       if r.Type == config.Type && r.Value == config.Value {
+                               alreadyPresent = true
+                               break
+                       }
+               }
+               if !alreadyPresent {
+                       in.Configuration = append(in.Configuration, config)
+               }
+       }
+}
+
 // Configurations --
 func (in *IntegrationSpec) Configurations() []ConfigurationSpec {
        if in == nil {
diff --git a/pkg/trait/kamelets.go b/pkg/trait/kamelets.go
index 55b61a2..2a98a3a 100644
--- a/pkg/trait/kamelets.go
+++ b/pkg/trait/kamelets.go
@@ -45,8 +45,25 @@ type kameletsTrait struct {
        List string `property:"list"`
 }
 
+type configurationKey struct {
+       kamelet         string
+       configurationID string
+}
+
+func newConfigurationKey(kamelet, configurationID string) configurationKey {
+       return configurationKey{
+               kamelet:         kamelet,
+               configurationID: configurationID,
+       }
+}
+
+const (
+       kameletLabel              = "camel.apache.org/kamelet"
+       kameletConfigurationLabel = "camel.apache.org/kamelet.configuration"
+)
+
 var (
-       kameletNameRegexp = 
regexp.MustCompile("kamelet:(?://)?([a-z0-9-.]+)(?:$|[^a-z0-9-.].*)")
+       kameletNameRegexp = 
regexp.MustCompile("kamelet:(?://)?([a-z0-9-.]+(/[a-z0-9-.]+)?)(?:$|[^a-z0-9-.].*)")
 )
 
 func newKameletsTrait() Trait {
@@ -79,19 +96,21 @@ func (t *kameletsTrait) Configure(e *Environment) (bool, 
error) {
 
        }
 
-       return len(t.getKamelets()) > 0, nil
+       return len(t.getKameletKeys()) > 0, nil
 }
 
 func (t *kameletsTrait) Apply(e *Environment) error {
        if err := t.addKamelets(e); err != nil {
                return err
        }
-
+       if err := t.addConfigurationSecrets(e); err != nil {
+               return err
+       }
        return nil
 }
 
 func (t *kameletsTrait) addKamelets(e *Environment) error {
-       for _, k := range t.getKamelets() {
+       for _, k := range t.getKameletKeys() {
                var kamelet v1alpha1.Kamelet
                key := client.ObjectKey{
                        Namespace: e.Integration.Namespace,
@@ -168,14 +187,75 @@ func (t *kameletsTrait) addKameletAsSource(e 
*Environment, kamelet v1alpha1.Kame
        return nil
 }
 
-func (t *kameletsTrait) getKamelets() []string {
+func (t *kameletsTrait) addConfigurationSecrets(e *Environment) error {
+       for _, k := range t.getConfigurationKeys() {
+               var options = metav1.ListOptions{
+                       LabelSelector: fmt.Sprintf("%s=%s", kameletLabel, 
k.kamelet),
+               }
+               if k.configurationID != "" {
+                       options.LabelSelector = fmt.Sprintf("%s=%s,%s=%s", 
kameletLabel, k.kamelet, kameletConfigurationLabel, k.configurationID)
+               }
+               secrets, err := 
t.Client.CoreV1().Secrets(e.Integration.Namespace).List(options)
+               if err != nil {
+                       return err
+               }
+
+               for _, item := range secrets.Items {
+                       if item.Labels != nil && 
item.Labels[kameletConfigurationLabel] != k.configurationID {
+                               continue
+                       }
+
+                       
e.Integration.Status.AddConfigurationsIfMissing(v1.ConfigurationSpec{
+                               Type:  "secret",
+                               Value: item.Name,
+                       })
+               }
+       }
+       return nil
+}
+
+func (t *kameletsTrait) getKameletKeys() []string {
        answer := make([]string, 0)
        for _, item := range strings.Split(t.List, ",") {
                i := strings.Trim(item, " \t\"")
+               if strings.Contains(i, "/") {
+                       i = strings.SplitN(i, "/", 2)[0]
+               }
                if i != "" {
-                       answer = append(answer, i)
+                       util.StringSliceUniqueAdd(&answer, i)
+               }
+       }
+       sort.Strings(answer)
+       return answer
+}
+
+func (t *kameletsTrait) getConfigurationKeys() []configurationKey {
+       answer := make([]configurationKey, 0)
+       for _, item := range t.getKameletKeys() {
+               answer = append(answer, newConfigurationKey(item, ""))
+       }
+       for _, item := range strings.Split(t.List, ",") {
+               i := strings.Trim(item, " \t\"")
+               if strings.Contains(i, "/") {
+                       parts := strings.SplitN(i, "/", 2)
+                       newKey := newConfigurationKey(parts[0], parts[1])
+                       alreadyPresent := false
+                       for _, existing := range answer {
+                               if existing == newKey {
+                                       alreadyPresent = true
+                                       break
+                               }
+                       }
+                       if !alreadyPresent {
+                               answer = append(answer, newKey)
+                       }
                }
        }
+       sort.Slice(answer, func(i, j int) bool {
+               o1 := answer[i]
+               o2 := answer[j]
+               return o1.kamelet < o2.kamelet || (o1.kamelet == o2.kamelet && 
o1.configurationID < o2.configurationID)
+       })
        return answer
 }
 
@@ -236,7 +316,7 @@ func integrationSourceFromKameletSource(e *Environment, 
kamelet v1alpha1.Kamelet
 func extractKamelets(uris []string) (kamelets []string) {
        for _, uri := range uris {
                matches := kameletNameRegexp.FindStringSubmatch(uri)
-               if len(matches) == 2 {
+               if len(matches) > 1 {
                        kamelets = append(kamelets, matches[1])
                }
        }
diff --git a/pkg/trait/kamelets_test.go b/pkg/trait/kamelets_test.go
index 500baba..4916046 100644
--- a/pkg/trait/kamelets_test.go
+++ b/pkg/trait/kamelets_test.go
@@ -64,7 +64,17 @@ func TestConfigurationWithKamelets(t *testing.T) {
        enabled, err := trait.Configure(environment)
        assert.NoError(t, err)
        assert.True(t, enabled)
-       assert.Equal(t, []string{"c0", "c1", "c2", "complex-.-.-1a", 
"complex-.-.-1b", "complex-.-.-1c"}, trait.getKamelets())
+       assert.Equal(t, []string{"c0", "c1", "c2", "complex-.-.-1a", 
"complex-.-.-1b", "complex-.-.-1c"}, trait.getKameletKeys())
+       assert.Equal(t, []configurationKey{
+               newConfigurationKey("c0", ""),
+               newConfigurationKey("c1", ""),
+               newConfigurationKey("c2", ""),
+               newConfigurationKey("complex-.-.-1a", ""),
+               newConfigurationKey("complex-.-.-1b", ""),
+               newConfigurationKey("complex-.-.-1b", "a"),
+               newConfigurationKey("complex-.-.-1c", ""),
+               newConfigurationKey("complex-.-.-1c", "b"),
+       }, trait.getConfigurationKeys())
 }
 
 func TestKameletLookup(t *testing.T) {
@@ -93,7 +103,7 @@ func TestKameletLookup(t *testing.T) {
        enabled, err := trait.Configure(environment)
        assert.NoError(t, err)
        assert.True(t, enabled)
-       assert.Equal(t, []string{"timer"}, trait.getKamelets())
+       assert.Equal(t, []string{"timer"}, trait.getKameletKeys())
 
        err = trait.Apply(environment)
        assert.NoError(t, err)
@@ -141,7 +151,7 @@ func TestKameletSecondarySourcesLookup(t *testing.T) {
        enabled, err := trait.Configure(environment)
        assert.NoError(t, err)
        assert.True(t, enabled)
-       assert.Equal(t, []string{"timer"}, trait.getKamelets())
+       assert.Equal(t, []string{"timer"}, trait.getKameletKeys())
 
        err = trait.Apply(environment)
        assert.NoError(t, err)
@@ -191,7 +201,7 @@ func TestNonYAMLKameletLookup(t *testing.T) {
        enabled, err := trait.Configure(environment)
        assert.NoError(t, err)
        assert.True(t, enabled)
-       assert.Equal(t, []string{"timer"}, trait.getKamelets())
+       assert.Equal(t, []string{"timer"}, trait.getKameletKeys())
 
        err = trait.Apply(environment)
        assert.NoError(t, err)
@@ -237,7 +247,7 @@ func TestErrorMultipleKameletSources(t *testing.T) {
        enabled, err := trait.Configure(environment)
        assert.NoError(t, err)
        assert.True(t, enabled)
-       assert.Equal(t, []string{"timer"}, trait.getKamelets())
+       assert.Equal(t, []string{"timer"}, trait.getKameletKeys())
 
        err = trait.Apply(environment)
        assert.Error(t, err)
@@ -302,7 +312,7 @@ func TestMultipleKamelets(t *testing.T) {
        enabled, err := trait.Configure(environment)
        assert.NoError(t, err)
        assert.True(t, enabled)
-       assert.Equal(t, []string{"logger", "timer"}, trait.getKamelets())
+       assert.Equal(t, []string{"logger", "timer"}, trait.getKameletKeys())
 
        err = trait.Apply(environment)
        assert.NoError(t, err)
@@ -337,6 +347,134 @@ func TestMultipleKamelets(t *testing.T) {
        assert.Equal(t, []string{"camel:log", "camel:tbd", "camel:timer", 
"camel:xxx"}, environment.Integration.Status.Dependencies)
 }
 
+func TestKameletConfigLookup(t *testing.T) {
+       trait, environment := createKameletsTestEnvironment(`
+- from:
+    uri: kamelet:timer
+    steps:
+    - to: log:info
+`, &v1alpha1.Kamelet{
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "test",
+                       Name:      "timer",
+               },
+               Spec: v1alpha1.KameletSpec{
+                       Flow: &v1.Flow{
+                               "from": map[string]interface{}{
+                                       "uri": "timer:tick",
+                               },
+                       },
+                       Dependencies: []string{
+                               "camel:timer",
+                               "camel:log",
+                       },
+               },
+       }, &corev1.Secret{
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "test",
+                       Name:      "my-secret",
+                       Labels: map[string]string{
+                               "camel.apache.org/kamelet": "timer",
+                       },
+               },
+       }, &corev1.Secret{
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "test",
+                       Name:      "my-secret2",
+                       Labels: map[string]string{
+                               "camel.apache.org/kamelet":               
"timer",
+                               "camel.apache.org/kamelet.configuration": "id2",
+                       },
+               },
+       }, &corev1.Secret{
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "test",
+                       Name:      "my-secret3",
+                       Labels: map[string]string{
+                               "camel.apache.org/kamelet": "timer",
+                       },
+               },
+       })
+       enabled, err := trait.Configure(environment)
+       assert.NoError(t, err)
+       assert.True(t, enabled)
+       assert.Equal(t, []string{"timer"}, trait.getKameletKeys())
+       assert.Equal(t, []configurationKey{newConfigurationKey("timer", "")}, 
trait.getConfigurationKeys())
+
+       err = trait.Apply(environment)
+       assert.NoError(t, err)
+       assert.Len(t, environment.Integration.Status.Configuration, 2)
+       assert.Contains(t, environment.Integration.Status.Configuration, 
v1.ConfigurationSpec{Type: "secret", Value: "my-secret"})
+       assert.NotContains(t, environment.Integration.Status.Configuration, 
v1.ConfigurationSpec{Type: "secret", Value: "my-secret2"})
+       assert.Contains(t, environment.Integration.Status.Configuration, 
v1.ConfigurationSpec{Type: "secret", Value: "my-secret3"})
+}
+
+func TestKameletNamedConfigLookup(t *testing.T) {
+       trait, environment := createKameletsTestEnvironment(`
+- from:
+    uri: kamelet:timer/id2
+    steps:
+    - to: log:info
+`, &v1alpha1.Kamelet{
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "test",
+                       Name:      "timer",
+               },
+               Spec: v1alpha1.KameletSpec{
+                       Flow: &v1.Flow{
+                               "from": map[string]interface{}{
+                                       "uri": "timer:tick",
+                               },
+                       },
+                       Dependencies: []string{
+                               "camel:timer",
+                               "camel:log",
+                       },
+               },
+       }, &corev1.Secret{
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "test",
+                       Name:      "my-secret",
+                       Labels: map[string]string{
+                               "camel.apache.org/kamelet": "timer",
+                       },
+               },
+       }, &corev1.Secret{
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "test",
+                       Name:      "my-secret2",
+                       Labels: map[string]string{
+                               "camel.apache.org/kamelet":               
"timer",
+                               "camel.apache.org/kamelet.configuration": "id2",
+                       },
+               },
+       }, &corev1.Secret{
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "test",
+                       Name:      "my-secret3",
+                       Labels: map[string]string{
+                               "camel.apache.org/kamelet":               
"timer",
+                               "camel.apache.org/kamelet.configuration": "id3",
+                       },
+               },
+       })
+       enabled, err := trait.Configure(environment)
+       assert.NoError(t, err)
+       assert.True(t, enabled)
+       assert.Equal(t, []string{"timer"}, trait.getKameletKeys())
+       assert.Equal(t, []configurationKey{
+               newConfigurationKey("timer", ""),
+               newConfigurationKey("timer", "id2"),
+       }, trait.getConfigurationKeys())
+
+       err = trait.Apply(environment)
+       assert.NoError(t, err)
+       assert.Len(t, environment.Integration.Status.Configuration, 2)
+       assert.Contains(t, environment.Integration.Status.Configuration, 
v1.ConfigurationSpec{Type: "secret", Value: "my-secret"})
+       assert.Contains(t, environment.Integration.Status.Configuration, 
v1.ConfigurationSpec{Type: "secret", Value: "my-secret2"})
+       assert.NotContains(t, environment.Integration.Status.Configuration, 
v1.ConfigurationSpec{Type: "secret", Value: "my-secret3"})
+}
+
 func createKameletsTestEnvironment(flow string, objects ...runtime.Object) 
(*kameletsTrait, *Environment) {
        catalog, _ := camel.DefaultCatalog()
 
diff --git a/pkg/util/test/client.go b/pkg/util/test/client.go
index d3df07b..b223f95 100644
--- a/pkg/util/test/client.go
+++ b/pkg/util/test/client.go
@@ -20,9 +20,9 @@ package test
 import (
        "github.com/apache/camel-k/pkg/apis"
        "github.com/apache/camel-k/pkg/client"
-
        "k8s.io/apimachinery/pkg/runtime"
        "k8s.io/client-go/kubernetes"
+       fakeclientset "k8s.io/client-go/kubernetes/fake"
        clientscheme "k8s.io/client-go/kubernetes/scheme"
        "k8s.io/client-go/rest"
 
@@ -40,10 +40,25 @@ func NewFakeClient(initObjs ...runtime.Object) 
(client.Client, error) {
        }
 
        c := fake.NewFakeClientWithScheme(scheme, initObjs...)
+       filtered := make([]runtime.Object, 0, len(initObjs))
+       for _, o := range initObjs {
+               kinds, _, _ := scheme.ObjectKinds(o)
+               allow := true
+               for _, k := range kinds {
+                       if k.Group == "camel.apache.org" {
+                               allow = false
+                               break
+                       }
+               }
+               if allow {
+                       filtered = append(filtered, o)
+               }
+       }
+       clientset := fakeclientset.NewSimpleClientset(filtered...)
 
        return &FakeClient{
                Client:    c,
-               Interface: nil,
+               Interface: clientset,
        }, nil
 }
 

Reply via email to