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 <[email protected]> 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) {
