You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pc...@apache.org on 2022/01/07 13:48:26 UTC

[camel-k] 20/24: chore(trait): autogen configmap ownership

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

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

commit 7b643b7934994b6a6ba82d11fcb1182a053a826e
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Tue Jan 4 11:38:20 2022 +0100

    chore(trait): autogen configmap ownership
---
 e2e/support/test_support.go    |  2 +-
 pkg/cmd/run.go                 | 30 ++++++++----------------------
 pkg/cmd/run_help.go            | 27 ---------------------------
 pkg/trait/mount.go             | 34 ++++++++++++++++++++++++++++------
 pkg/trait/mount_test.go        |  6 +++++-
 pkg/trait/openapi.go           |  4 ++++
 pkg/util/kubernetes/factory.go | 13 ++++++++++---
 pkg/util/resource/config.go    |  2 +-
 8 files changed, 57 insertions(+), 61 deletions(-)

diff --git a/e2e/support/test_support.go b/e2e/support/test_support.go
index 8d75eb6..319ab49 100644
--- a/e2e/support/test_support.go
+++ b/e2e/support/test_support.go
@@ -929,7 +929,7 @@ func AutogeneratedConfigmapsCount(ns string) func() int {
 		err := TestClient().List(TestContext, &lst,
 			ctrl.InNamespace(ns),
 			ctrl.MatchingLabels{
-				"camel.apache.org/autogenerated": "true",
+				kubernetes.ConfigMapAutogenLabel: "true",
 			})
 		if err != nil {
 			panic(err)
diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go
index 35f2c0a..732e1da 100644
--- a/pkg/cmd/run.go
+++ b/pkg/cmd/run.go
@@ -575,22 +575,18 @@ func (o *runCmdOptions) createOrUpdateIntegration(cmd *cobra.Command, c client.C
 		return nil, err
 	}
 
-	generatedConfigmaps := make([]*corev1.ConfigMap, 0)
-	resCms, err := o.parseAndConvertToTrait(c, integration, o.Resources, resource.ParseResource, func(c *resource.Config) string { return c.String() }, "mount.resources")
+	err = o.parseAndConvertToTrait(c, integration, o.Resources, resource.ParseResource, func(c *resource.Config) string { return c.String() }, "mount.resources")
 	if err != nil {
 		return nil, err
 	}
-	generatedConfigmaps = append(generatedConfigmaps, resCms...)
-	confCms, err := o.parseAndConvertToTrait(c, integration, o.Configs, resource.ParseConfig, func(c *resource.Config) string { return c.String() }, "mount.configs")
+	err = o.parseAndConvertToTrait(c, integration, o.Configs, resource.ParseConfig, func(c *resource.Config) string { return c.String() }, "mount.configs")
 	if err != nil {
 		return nil, err
 	}
-	generatedConfigmaps = append(generatedConfigmaps, confCms...)
-	oAPICms, err := o.parseAndConvertToTrait(c, integration, o.OpenAPIs, resource.ParseConfig, func(c *resource.Config) string { return c.Name() }, "openapi.configmaps")
+	err = o.parseAndConvertToTrait(c, integration, o.OpenAPIs, resource.ParseConfig, func(c *resource.Config) string { return c.Name() }, "openapi.configmaps")
 	if err != nil {
 		return nil, err
 	}
-	generatedConfigmaps = append(generatedConfigmaps, oAPICms...)
 
 	for _, item := range o.Dependencies {
 		integration.Spec.AddDependency(item)
@@ -679,12 +675,6 @@ func (o *runCmdOptions) createOrUpdateIntegration(cmd *cobra.Command, c client.C
 		return nil, err
 	}
 
-	if generatedConfigmaps != nil {
-		err = bindGeneratedConfigmapsToIntegration(o.Context, c, integration, generatedConfigmaps)
-		if err != nil {
-			return integration, err
-		}
-	}
 	return integration, nil
 }
 
@@ -692,24 +682,20 @@ func (o *runCmdOptions) parseAndConvertToTrait(
 	c client.Client, integration *v1.Integration, params []string,
 	parse func(string) (*resource.Config, error),
 	convert func(*resource.Config) string,
-	traitParam string) ([]*corev1.ConfigMap, error) {
-	generatedCms := make([]*corev1.ConfigMap, 0)
+	traitParam string) error {
 	for _, param := range params {
 		config, err := parse(param)
 		if err != nil {
-			return nil, err
+			return err
 		}
 		// We try to autogenerate a configmap
-		maybeGenCm, err := parseConfigAndGenCm(o.Context, c, config, integration, o.Compression)
+		_, err = parseConfigAndGenCm(o.Context, c, config, integration, o.Compression)
 		if err != nil {
-			return nil, err
-		}
-		if maybeGenCm != nil {
-			generatedCms = append(generatedCms, maybeGenCm)
+			return err
 		}
 		o.Traits = append(o.Traits, convertToTrait(convert(config), traitParam))
 	}
-	return generatedCms, nil
+	return nil
 }
 
 func convertToTrait(value, traitParameter string) string {
diff --git a/pkg/cmd/run_help.go b/pkg/cmd/run_help.go
index e9f9758..2690154 100644
--- a/pkg/cmd/run_help.go
+++ b/pkg/cmd/run_help.go
@@ -30,7 +30,6 @@ import (
 	"github.com/apache/camel-k/pkg/util/resource"
 	"github.com/magiconair/properties"
 	corev1 "k8s.io/api/core/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
 //nolint
@@ -162,29 +161,3 @@ func extractProperties(value string) (*properties.Properties, error) {
 func keyValueProps(value string) (*properties.Properties, error) {
 	return properties.Load([]byte(value), properties.UTF8)
 }
-
-func bindGeneratedConfigmapsToIntegration(ctx context.Context, c client.Client, i *v1.Integration, configmaps []*corev1.ConfigMap) error {
-	controller := true
-	blockOwnerDeletion := true
-	for _, cm := range configmaps {
-		cm.ObjectMeta.Labels[v1.IntegrationLabel] = i.Name
-		cm.ObjectMeta.Labels["camel.apache.org/autogenerated"] = "true"
-		// set owner references
-		cm.ObjectMeta.OwnerReferences = []metav1.OwnerReference{
-			{
-				Kind:               v1.IntegrationKind,
-				APIVersion:         v1.SchemeGroupVersion.String(),
-				Name:               i.Name,
-				UID:                i.UID,
-				Controller:         &controller,
-				BlockOwnerDeletion: &blockOwnerDeletion,
-			},
-		}
-		err := c.Update(ctx, cm)
-		if err != nil {
-			return err
-		}
-	}
-
-	return nil
-}
diff --git a/pkg/trait/mount.go b/pkg/trait/mount.go
index 18114bb..3fc6b74 100644
--- a/pkg/trait/mount.go
+++ b/pkg/trait/mount.go
@@ -32,15 +32,21 @@ import (
 	utilResource "github.com/apache/camel-k/pkg/util/resource"
 )
 
-// The Mount trait can be used to configure volumes mounted on the Integration Pod.
+// The Mount trait can be used to configure volumes mounted on the Integration Pods.
 //
 // +camel-k:trait=mount
 // nolint: tagliatelle
 type mountTrait struct {
 	BaseTrait `property:",squash"`
-	// A list of configuration pointing to configmap/secret. Syntax: [configmap|secret]:name[key], where name represents the resource name and key optionally represents the resource key to be filtered
+	// A list of configuration pointing to configmap/secret.
+	// The configuration are expected to be ÙTF-8 resources as they are processed by runtime Camel Context and tried to be parsed as property files.
+	// They are also made available on the classpath in order to ease their usage directly from the Route.
+	// Syntax: [configmap|secret]:name[key], where name represents the resource name and key optionally represents the resource key to be filtered
 	Configs []string `property:"configs" json:"configs,omitempty"`
-	// A list of resources pointing to configmap/secret. Syntax: [configmap|secret]:name[/key][@path], where name represents the resource name, key optionally represents the resource key to be filtered and path represents the destination path
+	// A list of resources (text or binary content) pointing to configmap/secret.
+	// The resources are expected to be any resource type (text or binary content).
+	// The destination path can be either a default location or any path specified by the user.
+	// Syntax: [configmap|secret]:name[/key][@path], where name represents the resource name, key optionally represents the resource key to be filtered and path represents the destination path
 	Resources []string `property:"resources" json:"resources,omitempty"`
 	// A list of Persistent Volume Claims to be mounted. Syntax: [pvcname:/container/path]
 	Volumes []string `property:"volumes" json:"volumes,omitempty"`
@@ -58,7 +64,8 @@ func (t *mountTrait) Configure(e *Environment) (bool, error) {
 		return false, nil
 	}
 
-	if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization) && !e.IntegrationInRunningPhases() {
+	if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) ||
+		(!e.IntegrationInPhase(v1.IntegrationPhaseInitialization) && !e.IntegrationInRunningPhases()) {
 		return false, nil
 	}
 
@@ -121,7 +128,7 @@ func (t *mountTrait) Apply(e *Environment) error {
 		// Volumes declared in the Integration resources
 		e.configureVolumesAndMounts(volumes, &container.VolumeMounts)
 		// Volumes declared in the trait config/resource options
-		err := t.configureVolumesAndMounts(volumes, &container.VolumeMounts)
+		err := t.configureVolumesAndMounts(e, volumes, &container.VolumeMounts)
 		if err != nil {
 			return err
 		}
@@ -130,9 +137,10 @@ func (t *mountTrait) Apply(e *Environment) error {
 	return nil
 }
 
-func (t *mountTrait) configureVolumesAndMounts(vols *[]corev1.Volume, mnts *[]corev1.VolumeMount) error {
+func (t *mountTrait) configureVolumesAndMounts(e *Environment, vols *[]corev1.Volume, mnts *[]corev1.VolumeMount) error {
 	for _, c := range t.Configs {
 		if conf, parseErr := utilResource.ParseConfig(c); parseErr == nil {
+			t.attachResource(e, conf)
 			t.mountResource(vols, mnts, conf)
 		} else {
 			return parseErr
@@ -140,6 +148,7 @@ func (t *mountTrait) configureVolumesAndMounts(vols *[]corev1.Volume, mnts *[]co
 	}
 	for _, r := range t.Resources {
 		if res, parseErr := utilResource.ParseResource(r); parseErr == nil {
+			t.attachResource(e, res)
 			t.mountResource(vols, mnts, res)
 		} else {
 			return parseErr
@@ -156,6 +165,19 @@ func (t *mountTrait) configureVolumesAndMounts(vols *[]corev1.Volume, mnts *[]co
 	return nil
 }
 
+// attachResource is in charge to filter the autogenerated configmap and attach to the Integration resources.
+// The owner trait will be in charge to bind it accordingly.
+func (t *mountTrait) attachResource(e *Environment, conf *utilResource.Config) {
+	if conf.StorageType() == utilResource.StorageTypeConfigmap {
+		// verify if it was autogenerated
+		cm := kubernetes.LookupConfigmap(e.Ctx, e.Client, e.Integration.Namespace, conf.Name())
+		if cm != nil && cm.ObjectMeta.Labels[kubernetes.ConfigMapAutogenLabel] == "true" {
+			refCm := kubernetes.NewConfigMap(e.Integration.Namespace, conf.Name(), "", "", "", nil)
+			e.Resources.Add(refCm)
+		}
+	}
+}
+
 func (t *mountTrait) mountResource(vols *[]corev1.Volume, mnts *[]corev1.VolumeMount, conf *utilResource.Config) {
 	refName := kubernetes.SanitizeLabel(conf.Name())
 	vol := getVolume(refName, string(conf.StorageType()), conf.Name(), conf.Key(), conf.Key())
diff --git a/pkg/trait/mount_test.go b/pkg/trait/mount_test.go
index eee4bc0..9221244 100644
--- a/pkg/trait/mount_test.go
+++ b/pkg/trait/mount_test.go
@@ -18,6 +18,7 @@ limitations under the License.
 package trait
 
 import (
+	"context"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
@@ -114,7 +115,7 @@ func TestMountVolumesIntegrationPhaseInitialization(t *testing.T) {
 
 	assert.Nil(t, err)
 	assert.NotEmpty(t, environment.ExecutedTraits)
-	assert.NotNil(t, environment.GetTrait("mount"))
+	assert.Nil(t, environment.GetTrait("mount"))
 
 	s := environment.Resources.GetDeployment(func(service *appsv1.Deployment) bool {
 		return service.Name == "hello"
@@ -124,12 +125,15 @@ func TestMountVolumesIntegrationPhaseInitialization(t *testing.T) {
 
 func getNominalEnv(t *testing.T, traitCatalog *Catalog) *Environment {
 	t.Helper()
+	fakeClient, _ := test.NewFakeClient()
 	catalog, _ := camel.DefaultCatalog()
 	compressedRoute, _ := gzip.CompressBase64([]byte(`from("undertow:test").log("hello")`))
 
 	return &Environment{
 		CamelCatalog: catalog,
 		Catalog:      traitCatalog,
+		Ctx:          context.Background(),
+		Client:       fakeClient,
 		Integration: &v1.Integration{
 			ObjectMeta: metav1.ObjectMeta{
 				Name:      "hello",
diff --git a/pkg/trait/openapi.go b/pkg/trait/openapi.go
index 43c8791..24f49b7 100644
--- a/pkg/trait/openapi.go
+++ b/pkg/trait/openapi.go
@@ -140,6 +140,10 @@ func (t *openAPITrait) generateFromConfigmaps(e *Environment, tmpDir string) ([]
 		if cm == nil {
 			return nil, fmt.Errorf("could not find any configmap with name: %s", configmap)
 		}
+		if cm.ObjectMeta.Labels[kubernetes.ConfigMapAutogenLabel] == "true" {
+			refCm := kubernetes.NewConfigMap(e.Integration.Namespace, configmap, "", "", "", nil)
+			e.Resources.Add(refCm)
+		}
 		// Iterate over each configmap key which may hold a different OpenAPI spec
 		for k, v := range cm.Data {
 			dataSpecs = append(dataSpecs, v1.DataSpec{
diff --git a/pkg/util/kubernetes/factory.go b/pkg/util/kubernetes/factory.go
index 9d32be1..c79b76b 100644
--- a/pkg/util/kubernetes/factory.go
+++ b/pkg/util/kubernetes/factory.go
@@ -33,6 +33,12 @@ var (
 	validResourceRequirementsRegexp = regexp.MustCompile(`^(requests|limits)\.(memory|cpu)=([\w\.]+)$`)
 )
 
+// ConfigMapAutogenLabel -- .
+const ConfigMapAutogenLabel = "camel.apache.org/generated"
+
+// ConfigMapOriginalFileNameLabel -- .
+const ConfigMapOriginalFileNameLabel = "camel.apache.org/filename"
+
 // NewTolerations build an array of Tolerations from an array of string.
 func NewTolerations(taints []string) ([]corev1.Toleration, error) {
 	tolerations := make([]corev1.Toleration, 0)
@@ -116,8 +122,8 @@ func NewResourceRequirements(reqs []string) (corev1.ResourceRequirements, error)
 	return resReq, nil
 }
 
-// NewConfigmap will create a Configmap.
-func NewConfigmap(namespace, cmName, originalFilename string, generatedKey string,
+// NewConfigMap will create a ConfigMap.
+func NewConfigMap(namespace, cmName, originalFilename string, generatedKey string,
 	textData string, binaryData []byte) *corev1.ConfigMap {
 	immutable := true
 	cm := corev1.ConfigMap{
@@ -129,7 +135,8 @@ func NewConfigmap(namespace, cmName, originalFilename string, generatedKey strin
 			Name:      cmName,
 			Namespace: namespace,
 			Labels: map[string]string{
-				"camel.apache.org/filename": originalFilename,
+				ConfigMapOriginalFileNameLabel: originalFilename,
+				ConfigMapAutogenLabel:          "true",
 			},
 		},
 		Immutable: &immutable,
diff --git a/pkg/util/resource/config.go b/pkg/util/resource/config.go
index 41b0176..56703a4 100644
--- a/pkg/util/resource/config.go
+++ b/pkg/util/resource/config.go
@@ -232,7 +232,7 @@ func ConvertFileToConfigmap(ctx context.Context, c client.Client, config *Config
 		config.destinationPath = filepath.Dir(config.DestinationPath())
 	}
 	genCmName := fmt.Sprintf("cm-%s", hashFrom([]byte(integrationName), []byte(content), rawContent))
-	cm := kubernetes.NewConfigmap(namespace, genCmName, filepath.Base(config.Name()), config.Key(), content, rawContent)
+	cm := kubernetes.NewConfigMap(namespace, genCmName, filepath.Base(config.Name()), config.Key(), content, rawContent)
 	err := c.Create(ctx, cm)
 	if err != nil {
 		if k8serrors.IsAlreadyExists(err) {