You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ts...@apache.org on 2022/05/18 08:12:08 UTC

[camel-k] branch main updated: chore(cmd/trait): refactor cmd & trait packages

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

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


The following commit(s) were added to refs/heads/main by this push:
     new d9f10e963 chore(cmd/trait): refactor cmd & trait packages
d9f10e963 is described below

commit d9f10e963213b6dec74abe594e77270145c0b40e
Author: Tadayoshi Sato <sa...@gmail.com>
AuthorDate: Tue May 17 15:18:18 2022 +0900

    chore(cmd/trait): refactor cmd & trait packages
---
 pkg/cmd/trait_help.go                              | 107 ----------------
 pkg/cmd/trait_support.go                           | 136 +++++++++++++++++++++
 pkg/trait/{trait_types_test.go => test_support.go} |  16 ---
 pkg/trait/trait_types_test.go                      | 133 +++++++++-----------
 pkg/trait/util_test.go                             |  79 ------------
 5 files changed, 194 insertions(+), 277 deletions(-)

diff --git a/pkg/cmd/trait_help.go b/pkg/cmd/trait_help.go
index b56e8c69e..0ef7bc9af 100644
--- a/pkg/cmd/trait_help.go
+++ b/pkg/cmd/trait_help.go
@@ -26,14 +26,12 @@ import (
 	"strings"
 
 	"github.com/fatih/structs"
-	"github.com/mitchellh/mapstructure"
 	"github.com/spf13/cobra"
 	"gopkg.in/yaml.v2"
 
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 	"github.com/apache/camel-k/pkg/resources"
 	"github.com/apache/camel-k/pkg/trait"
-	"github.com/apache/camel-k/pkg/util"
 	"github.com/apache/camel-k/pkg/util/indentedwriter"
 )
 
@@ -263,108 +261,3 @@ func outputTraits(descriptions []*traitDescription) (string, error) {
 		return nil
 	})
 }
-
-func validateTraits(catalog *trait.Catalog, traits []string) error {
-	tp := catalog.ComputeTraitsProperties()
-	for _, t := range traits {
-		kv := strings.SplitN(t, "=", 2)
-		prefix := kv[0]
-		if strings.Contains(prefix, "[") {
-			prefix = prefix[0:strings.Index(prefix, "[")]
-		}
-		if !util.StringSliceExists(tp, prefix) {
-			return fmt.Errorf("%s is not a valid trait property", t)
-		}
-	}
-
-	return nil
-}
-
-func configureTraits(options []string, catalog trait.Finder) (map[string]v1.TraitSpec, error) {
-	traits := make(map[string]map[string]interface{})
-
-	for _, option := range options {
-		parts := traitConfigRegexp.FindStringSubmatch(option)
-		if len(parts) < 4 {
-			return nil, errors.New("unrecognized config format (expected \"<trait>.<prop>=<value>\"): " + option)
-		}
-		id := parts[1]
-		fullProp := parts[2][1:]
-		value := parts[3]
-		if _, ok := traits[id]; !ok {
-			traits[id] = make(map[string]interface{})
-		}
-
-		propParts := util.ConfigTreePropertySplit(fullProp)
-		var current = traits[id]
-		if len(propParts) > 1 {
-			c, err := util.NavigateConfigTree(current, propParts[0:len(propParts)-1])
-			if err != nil {
-				return nil, err
-			}
-			if cc, ok := c.(map[string]interface{}); ok {
-				current = cc
-			} else {
-				return nil, errors.New("trait configuration cannot end with a slice")
-			}
-		}
-
-		prop := propParts[len(propParts)-1]
-		switch v := current[prop].(type) {
-		case []string:
-			current[prop] = append(v, value)
-		case string:
-			// Aggregate multiple occurrences of the same option into a string array, to emulate POSIX conventions.
-			// This enables executing:
-			// $ kamel run -t <trait>.<property>=<value_1> ... -t <trait>.<property>=<value_N>
-			// Or:
-			// $ kamel run --trait <trait>.<property>=<value_1>,...,<trait>.<property>=<value_N>
-			current[prop] = []string{v, value}
-		case nil:
-			current[prop] = value
-		}
-	}
-
-	specs := make(map[string]v1.TraitSpec)
-	for id, config := range traits {
-		t := catalog.GetTrait(id)
-		if t != nil {
-			// let's take a clone to prevent default values set at runtime from being serialized
-			zero := reflect.New(reflect.TypeOf(t)).Interface()
-			err := configureTrait(config, zero)
-			if err != nil {
-				return nil, err
-			}
-			data, err := json.Marshal(zero)
-			if err != nil {
-				return nil, err
-			}
-			var spec v1.TraitSpec
-			err = json.Unmarshal(data, &spec.Configuration)
-			if err != nil {
-				return nil, err
-			}
-			specs[id] = spec
-		}
-	}
-
-	return specs, nil
-}
-
-func configureTrait(config map[string]interface{}, trait interface{}) error {
-	md := mapstructure.Metadata{}
-
-	decoder, err := mapstructure.NewDecoder(
-		&mapstructure.DecoderConfig{
-			Metadata:         &md,
-			WeaklyTypedInput: true,
-			TagName:          "property",
-			Result:           &trait,
-		},
-	)
-	if err != nil {
-		return err
-	}
-
-	return decoder.Decode(config)
-}
diff --git a/pkg/cmd/trait_support.go b/pkg/cmd/trait_support.go
new file mode 100644
index 000000000..63fa23b9c
--- /dev/null
+++ b/pkg/cmd/trait_support.go
@@ -0,0 +1,136 @@
+/*
+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.
+*/
+
+package cmd
+
+import (
+	"encoding/json"
+	"errors"
+	"fmt"
+	"reflect"
+	"strings"
+
+	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+	"github.com/apache/camel-k/pkg/trait"
+	"github.com/apache/camel-k/pkg/util"
+	"github.com/mitchellh/mapstructure"
+)
+
+func validateTraits(catalog *trait.Catalog, traits []string) error {
+	tp := catalog.ComputeTraitsProperties()
+	for _, t := range traits {
+		kv := strings.SplitN(t, "=", 2)
+		prefix := kv[0]
+		if strings.Contains(prefix, "[") {
+			prefix = prefix[0:strings.Index(prefix, "[")]
+		}
+		if !util.StringSliceExists(tp, prefix) {
+			return fmt.Errorf("%s is not a valid trait property", t)
+		}
+	}
+
+	return nil
+}
+
+func configureTraits(options []string, catalog trait.Finder) (map[string]v1.TraitSpec, error) {
+	traits := make(map[string]map[string]interface{})
+
+	for _, option := range options {
+		parts := traitConfigRegexp.FindStringSubmatch(option)
+		if len(parts) < 4 {
+			return nil, errors.New("unrecognized config format (expected \"<trait>.<prop>=<value>\"): " + option)
+		}
+		id := parts[1]
+		fullProp := parts[2][1:]
+		value := parts[3]
+		if _, ok := traits[id]; !ok {
+			traits[id] = make(map[string]interface{})
+		}
+
+		propParts := util.ConfigTreePropertySplit(fullProp)
+		var current = traits[id]
+		if len(propParts) > 1 {
+			c, err := util.NavigateConfigTree(current, propParts[0:len(propParts)-1])
+			if err != nil {
+				return nil, err
+			}
+			if cc, ok := c.(map[string]interface{}); ok {
+				current = cc
+			} else {
+				return nil, errors.New("trait configuration cannot end with a slice")
+			}
+		}
+
+		prop := propParts[len(propParts)-1]
+		switch v := current[prop].(type) {
+		case []string:
+			current[prop] = append(v, value)
+		case string:
+			// Aggregate multiple occurrences of the same option into a string array, to emulate POSIX conventions.
+			// This enables executing:
+			// $ kamel run -t <trait>.<property>=<value_1> ... -t <trait>.<property>=<value_N>
+			// Or:
+			// $ kamel run --trait <trait>.<property>=<value_1>,...,<trait>.<property>=<value_N>
+			current[prop] = []string{v, value}
+		case nil:
+			current[prop] = value
+		}
+	}
+
+	specs := make(map[string]v1.TraitSpec)
+	for id, config := range traits {
+		t := catalog.GetTrait(id)
+		if t != nil {
+			// let's take a clone to prevent default values set at runtime from being serialized
+			zero := reflect.New(reflect.TypeOf(t)).Interface()
+			err := configureTrait(config, zero)
+			if err != nil {
+				return nil, err
+			}
+			data, err := json.Marshal(zero)
+			if err != nil {
+				return nil, err
+			}
+			var spec v1.TraitSpec
+			err = json.Unmarshal(data, &spec.Configuration)
+			if err != nil {
+				return nil, err
+			}
+			specs[id] = spec
+		}
+	}
+
+	return specs, nil
+}
+
+func configureTrait(config map[string]interface{}, trait interface{}) error {
+	md := mapstructure.Metadata{}
+
+	decoder, err := mapstructure.NewDecoder(
+		&mapstructure.DecoderConfig{
+			Metadata:         &md,
+			WeaklyTypedInput: true,
+			TagName:          "property",
+			Result:           &trait,
+		},
+	)
+	if err != nil {
+		return err
+	}
+
+	return decoder.Decode(config)
+}
diff --git a/pkg/trait/trait_types_test.go b/pkg/trait/test_support.go
similarity index 88%
copy from pkg/trait/trait_types_test.go
copy to pkg/trait/test_support.go
index 2a68853ae..137f0f91d 100644
--- a/pkg/trait/trait_types_test.go
+++ b/pkg/trait/test_support.go
@@ -18,9 +18,6 @@ limitations under the License.
 package trait
 
 import (
-	"testing"
-
-	"github.com/stretchr/testify/assert"
 	serving "knative.dev/serving/pkg/apis/serving/v1"
 
 	appsv1 "k8s.io/api/apps/v1"
@@ -32,19 +29,6 @@ import (
 	"github.com/apache/camel-k/pkg/util/kubernetes"
 )
 
-func TestMultilinePropertiesHandled(t *testing.T) {
-	e := Environment{
-		ApplicationProperties: map[string]string{
-			"prop": "multi\nline",
-		},
-		Integration: &v1.Integration{},
-	}
-	cm, err := e.computeApplicationProperties()
-	assert.NoError(t, err)
-	assert.NotNil(t, cm)
-	assert.Equal(t, "prop = multi\\nline\n", cm.Data["application.properties"])
-}
-
 func createNominalDeploymentTraitTest() (*Environment, *appsv1.Deployment) {
 	deployment := &appsv1.Deployment{
 		ObjectMeta: metav1.ObjectMeta{
diff --git a/pkg/trait/trait_types_test.go b/pkg/trait/trait_types_test.go
index 2a68853ae..9d3509de9 100644
--- a/pkg/trait/trait_types_test.go
+++ b/pkg/trait/trait_types_test.go
@@ -21,15 +21,8 @@ import (
 	"testing"
 
 	"github.com/stretchr/testify/assert"
-	serving "knative.dev/serving/pkg/apis/serving/v1"
-
-	appsv1 "k8s.io/api/apps/v1"
-	"k8s.io/api/batch/v1beta1"
-	corev1 "k8s.io/api/core/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
-	"github.com/apache/camel-k/pkg/util/kubernetes"
 )
 
 func TestMultilinePropertiesHandled(t *testing.T) {
@@ -45,89 +38,79 @@ func TestMultilinePropertiesHandled(t *testing.T) {
 	assert.Equal(t, "prop = multi\\nline\n", cm.Data["application.properties"])
 }
 
-func createNominalDeploymentTraitTest() (*Environment, *appsv1.Deployment) {
-	deployment := &appsv1.Deployment{
-		ObjectMeta: metav1.ObjectMeta{
-			Name: "integration-name",
-		},
-		Spec: appsv1.DeploymentSpec{
-			Template: corev1.PodTemplateSpec{},
-		},
-	}
-
-	environment := &Environment{
+func TestCollectConfigurationValues(t *testing.T) {
+	e := Environment{
 		Integration: &v1.Integration{
-			ObjectMeta: metav1.ObjectMeta{
-				Name: "integration-name",
-			},
-			Status: v1.IntegrationStatus{
-				Phase: v1.IntegrationPhaseDeploying,
+			Spec: v1.IntegrationSpec{
+				Configuration: []v1.ConfigurationSpec{
+					{Type: "configmap", Value: "my-cm-integration"},
+					{Type: "env", Value: "my-env-integration"},
+				},
 			},
 		},
-		Resources: kubernetes.NewCollection(deployment),
-	}
-
-	return environment, deployment
-}
-
-func createNominalMissingDeploymentTraitTest() *Environment {
-	environment := &Environment{
-		Integration: &v1.Integration{
-			ObjectMeta: metav1.ObjectMeta{
-				Name: "integration-name",
+		IntegrationKit: &v1.IntegrationKit{
+			Spec: v1.IntegrationKitSpec{
+				Configuration: []v1.ConfigurationSpec{
+					{Type: "configmap", Value: "my-cm-kit"},
+					{Type: "property", Value: "my-p-kit"},
+				},
 			},
-			Status: v1.IntegrationStatus{
-				Phase: v1.IntegrationPhaseDeploying,
+		},
+		Platform: &v1.IntegrationPlatform{
+			Spec: v1.IntegrationPlatformSpec{
+				Configuration: []v1.ConfigurationSpec{
+					{Type: "configmap", Value: "my-cm-platform"},
+					{Type: "secret", Value: "my-secret-platform"},
+					{Type: "property", Value: "my-p-platform"},
+					{Type: "env", Value: "my-env-platform"},
+				},
 			},
 		},
-		Resources: kubernetes.NewCollection(),
 	}
+	e.Platform.ResyncStatusFullConfig()
 
-	return environment
+	assert.Contains(t, e.collectConfigurationValues("configmap"), "my-cm-integration")
+	assert.Contains(t, e.collectConfigurationValues("secret"), "my-secret-platform")
+	assert.Contains(t, e.collectConfigurationValues("property"), "my-p-kit")
+	assert.Contains(t, e.collectConfigurationValues("env"), "my-env-integration")
 }
 
-func createNominalKnativeServiceTraitTest() (*Environment, *serving.Service) {
-	knativeService := &serving.Service{
-		ObjectMeta: metav1.ObjectMeta{
-			Name: "integration-name",
-		},
-		Spec: serving.ServiceSpec{},
-	}
-
-	environment := &Environment{
+func TestCollectConfigurationPairs(t *testing.T) {
+	e := Environment{
 		Integration: &v1.Integration{
-			ObjectMeta: metav1.ObjectMeta{
-				Name: "integration-name",
-			},
-			Status: v1.IntegrationStatus{
-				Phase: v1.IntegrationPhaseDeploying,
+			Spec: v1.IntegrationSpec{
+				Configuration: []v1.ConfigurationSpec{
+					{Type: "property", Value: "p1=integration"},
+					{Type: "property", Value: "p4=integration"},
+				},
 			},
 		},
-		Resources: kubernetes.NewCollection(knativeService),
-	}
-
-	return environment, knativeService
-}
-
-func createNominalCronJobTraitTest() (*Environment, *v1beta1.CronJob) {
-	cronJob := &v1beta1.CronJob{
-		ObjectMeta: metav1.ObjectMeta{
-			Name: "integration-name",
-		},
-		Spec: v1beta1.CronJobSpec{},
-	}
-
-	environment := &Environment{
-		Integration: &v1.Integration{
-			ObjectMeta: metav1.ObjectMeta{
-				Name: "integration-name",
+		IntegrationKit: &v1.IntegrationKit{
+			Spec: v1.IntegrationKitSpec{
+				Configuration: []v1.ConfigurationSpec{
+					{Type: "property", Value: "p1=kit"},
+					{Type: "property", Value: "p2=kit"},
+				},
 			},
-			Status: v1.IntegrationStatus{
-				Phase: v1.IntegrationPhaseDeploying,
+		},
+		Platform: &v1.IntegrationPlatform{
+			Spec: v1.IntegrationPlatformSpec{
+				Configuration: []v1.ConfigurationSpec{
+					{Type: "property", Value: "p1=platform"},
+					{Type: "property", Value: "p2=platform"},
+					{Type: "property", Value: "p3=platform"},
+					{Type: "property", Value: "p4=platform"},
+				},
 			},
 		},
-		Resources: kubernetes.NewCollection(cronJob),
 	}
-
-	return environment, cronJob
+	e.Platform.ResyncStatusFullConfig()
+
+	pairs := e.collectConfigurationPairs("property")
+	assert.Equal(t, pairs, []variable{
+		{Name: "p1", Value: "integration"},
+		{Name: "p2", Value: "kit"},
+		{Name: "p3", Value: "platform"},
+		{Name: "p4", Value: "integration"},
+	})
 }
diff --git a/pkg/trait/util_test.go b/pkg/trait/util_test.go
index d1488ad41..da4cd9589 100644
--- a/pkg/trait/util_test.go
+++ b/pkg/trait/util_test.go
@@ -21,87 +21,8 @@ import (
 	"testing"
 
 	"github.com/stretchr/testify/assert"
-
-	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 )
 
-func TestCollectConfigurationValues(t *testing.T) {
-	e := Environment{
-		Integration: &v1.Integration{
-			Spec: v1.IntegrationSpec{
-				Configuration: []v1.ConfigurationSpec{
-					{Type: "configmap", Value: "my-cm-integration"},
-					{Type: "env", Value: "my-env-integration"},
-				},
-			},
-		},
-		IntegrationKit: &v1.IntegrationKit{
-			Spec: v1.IntegrationKitSpec{
-				Configuration: []v1.ConfigurationSpec{
-					{Type: "configmap", Value: "my-cm-kit"},
-					{Type: "property", Value: "my-p-kit"},
-				},
-			},
-		},
-		Platform: &v1.IntegrationPlatform{
-			Spec: v1.IntegrationPlatformSpec{
-				Configuration: []v1.ConfigurationSpec{
-					{Type: "configmap", Value: "my-cm-platform"},
-					{Type: "secret", Value: "my-secret-platform"},
-					{Type: "property", Value: "my-p-platform"},
-					{Type: "env", Value: "my-env-platform"},
-				},
-			},
-		},
-	}
-	e.Platform.ResyncStatusFullConfig()
-
-	assert.Contains(t, e.collectConfigurationValues("configmap"), "my-cm-integration")
-	assert.Contains(t, e.collectConfigurationValues("secret"), "my-secret-platform")
-	assert.Contains(t, e.collectConfigurationValues("property"), "my-p-kit")
-	assert.Contains(t, e.collectConfigurationValues("env"), "my-env-integration")
-}
-
-func TestCollectConfigurationPairs(t *testing.T) {
-	e := Environment{
-		Integration: &v1.Integration{
-			Spec: v1.IntegrationSpec{
-				Configuration: []v1.ConfigurationSpec{
-					{Type: "property", Value: "p1=integration"},
-					{Type: "property", Value: "p4=integration"},
-				},
-			},
-		},
-		IntegrationKit: &v1.IntegrationKit{
-			Spec: v1.IntegrationKitSpec{
-				Configuration: []v1.ConfigurationSpec{
-					{Type: "property", Value: "p1=kit"},
-					{Type: "property", Value: "p2=kit"},
-				},
-			},
-		},
-		Platform: &v1.IntegrationPlatform{
-			Spec: v1.IntegrationPlatformSpec{
-				Configuration: []v1.ConfigurationSpec{
-					{Type: "property", Value: "p1=platform"},
-					{Type: "property", Value: "p2=platform"},
-					{Type: "property", Value: "p3=platform"},
-					{Type: "property", Value: "p4=platform"},
-				},
-			},
-		},
-	}
-	e.Platform.ResyncStatusFullConfig()
-
-	pairs := e.collectConfigurationPairs("property")
-	assert.Equal(t, pairs, []variable{
-		{Name: "p1", Value: "integration"},
-		{Name: "p2", Value: "kit"},
-		{Name: "p3", Value: "platform"},
-		{Name: "p4", Value: "integration"},
-	})
-}
-
 func TestBoolPointerFunctions(t *testing.T) {
 	trueP := BoolP(true)
 	falseP := BoolP(false)