This is an automated email from the ASF dual-hosted git repository. lburgazzoli pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel-k.git
The following commit(s) were added to refs/heads/master by this push: new 82c1a87 fix(owner): ensure lebsl/annotations are propagated to child resources 82c1a87 is described below commit 82c1a87f23ef035b44db28d4617301289f1e3a12 Author: lburgazzoli <lburgazz...@gmail.com> AuthorDate: Thu Mar 7 06:53:53 2019 +0100 fix(owner): ensure lebsl/annotations are propagated to child resources --- pkg/trait/owner.go | 123 +++++++++++++++++++++++++++++------------------- pkg/trait/owner_test.go | 78 ++++++++++++++++++++++++++++-- 2 files changed, 150 insertions(+), 51 deletions(-) diff --git a/pkg/trait/owner.go b/pkg/trait/owner.go index 4dd2a2e..5297e7d 100644 --- a/pkg/trait/owner.go +++ b/pkg/trait/owner.go @@ -20,10 +20,13 @@ package trait import ( "strings" + "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" "github.com/apache/camel-k/pkg/util/finalizer" + "github.com/pkg/errors" - "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" + serving "github.com/knative/serving/pkg/apis/serving/v1alpha1" + appsv1 "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -51,19 +54,6 @@ func (t *ownerTrait) Configure(e *Environment) (bool, error) { return false, nil } - ok, err := finalizer.Exists(e.Integration, finalizer.CamelIntegrationFinalizer) - if err != nil { - return false, errors.Wrap(err, "failed to read finalizer"+finalizer.CamelIntegrationFinalizer) - } - - if ok { - // - // do not enable this trait if the integration has - // a finalizer - // - return false, nil - } - return e.IntegrationInPhase(v1alpha1.IntegrationPhaseDeploying), nil } @@ -71,51 +61,88 @@ func (t *ownerTrait) Apply(e *Environment) error { controller := true blockOwnerDeletion := true - targetLabels := map[string]string{} - for _, k := range strings.Split(t.TargetLabels, ",") { - if v, ok := e.Integration.Labels[k]; ok { - targetLabels[k] = v + targetLabels := make(map[string]string) + if e.Integration.Labels != nil { + for _, k := range strings.Split(t.TargetLabels, ",") { + if v, ok := e.Integration.Labels[k]; ok { + targetLabels[k] = v + } } } - targetAnnotations := map[string]string{} - for _, k := range strings.Split(t.TargetAnnotations, ",") { - if v, ok := e.Integration.Annotations[k]; ok { - targetAnnotations[k] = v + targetAnnotations := make(map[string]string) + if e.Integration.Annotations != nil { + for _, k := range strings.Split(t.TargetAnnotations, ",") { + if v, ok := e.Integration.Annotations[k]; ok { + targetAnnotations[k] = v + } } } + ok, err := finalizer.Exists(e.Integration, finalizer.CamelIntegrationFinalizer) + if err != nil { + return errors.Wrap(err, "failed to read finalizer"+finalizer.CamelIntegrationFinalizer) + } + e.Resources.VisitMetaObject(func(res metav1.Object) { - // Add owner reference - references := []metav1.OwnerReference{ - { - APIVersion: e.Integration.APIVersion, - Kind: e.Integration.Kind, - Name: e.Integration.Name, - UID: e.Integration.UID, - Controller: &controller, - BlockOwnerDeletion: &blockOwnerDeletion, - }, + // + // do not add owner reference if the finalizer is set + // so resources are not automatically deleted by k8s + // when owner is deleted + // + if !ok { + references := []metav1.OwnerReference{ + { + APIVersion: e.Integration.APIVersion, + Kind: e.Integration.Kind, + Name: e.Integration.Name, + UID: e.Integration.UID, + Controller: &controller, + BlockOwnerDeletion: &blockOwnerDeletion, + }, + } + res.SetOwnerReferences(references) } - res.SetOwnerReferences(references) // Transfer annotations - annotations := res.GetAnnotations() - for k, v := range targetAnnotations { - if _, ok := annotations[k]; !ok { - annotations[k] = v - } - } - res.SetAnnotations(annotations) + t.propagateLabelAndAnnotations(res, targetLabels, targetAnnotations) + }) - // Transfer labels - labels := res.GetLabels() - for k, v := range targetLabels { - if _, ok := labels[k]; !ok { - labels[k] = v - } - } - res.SetLabels(labels) + e.Resources.VisitDeployment(func(deployment *appsv1.Deployment) { + t.propagateLabelAndAnnotations(&deployment.Spec.Template, targetLabels, targetAnnotations) + }) + + e.Resources.VisitKnativeService(func(service *serving.Service) { + t.propagateLabelAndAnnotations(&service.Spec.RunLatest.Configuration.RevisionTemplate, targetLabels, targetAnnotations) }) + return nil } + +func (t *ownerTrait) propagateLabelAndAnnotations(res metav1.Object, targetLabels map[string]string, targetAnnotations map[string]string) { + // Transfer annotations + annotations := res.GetAnnotations() + if annotations == nil { + annotations = make(map[string]string) + } + + for k, v := range targetAnnotations { + if _, ok := annotations[k]; !ok { + annotations[k] = v + } + } + res.SetAnnotations(annotations) + + // Transfer labels + labels := res.GetLabels() + if labels == nil { + labels = make(map[string]string) + } + + for k, v := range targetLabels { + if _, ok := labels[k]; !ok { + labels[k] = v + } + } + res.SetLabels(labels) +} diff --git a/pkg/trait/owner_test.go b/pkg/trait/owner_test.go index 27d0f47..2c08f0e 100644 --- a/pkg/trait/owner_test.go +++ b/pkg/trait/owner_test.go @@ -20,18 +20,90 @@ package trait import ( "testing" + "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" "github.com/apache/camel-k/pkg/util/finalizer" - "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" "github.com/stretchr/testify/assert" + + appsv1 "k8s.io/api/apps/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func TestOwnerWithFinalizer(t *testing.T) { - env := createTestEnv(t, v1alpha1.IntegrationPlatformClusterOpenShift, "camel:core") + env := SetUpOwnerEnvironment(t) env.Integration.Finalizers = []string{finalizer.CamelIntegrationFinalizer} processTestEnv(t, env) assert.NotEmpty(t, env.ExecutedTraits) - assert.Nil(t, env.GetTrait(ID("owner"))) + assert.NotNil(t, env.GetTrait(ID("owner"))) + + ValidateOwnerResources(t, env, false) +} + +func TestOwnerWithoutFinalizer(t *testing.T) { + env := SetUpOwnerEnvironment(t) + + processTestEnv(t, env) + + assert.NotEmpty(t, env.ExecutedTraits) + assert.NotNil(t, env.GetTrait(ID("owner"))) + + ValidateOwnerResources(t, env, true) +} + +func SetUpOwnerEnvironment(t *testing.T) *Environment { + env := createTestEnv(t, v1alpha1.IntegrationPlatformClusterOpenShift, "camel:core") + env.Integration.Spec.Traits = map[string]v1alpha1.IntegrationTraitSpec{ + "owner": { + Configuration: map[string]string{ + "target-labels": "com.mycompany/mylabel1", + "target-annotations": "com.mycompany/myannotation2", + }, + }, + } + + env.Integration.SetLabels(map[string]string{ + "com.mycompany/mylabel1": "myvalue1", + "com.mycompany/mylabel2": "myvalue2", + "org.apache.camel/l1": "l1", + }) + env.Integration.SetAnnotations(map[string]string{ + "com.mycompany/myannotation1": "myannotation1", + "com.mycompany/myannotation2": "myannotation2", + }) + + return env +} + +func ValidateOwnerResources(t *testing.T, env *Environment, withOwnerRef bool) { + assert.NotEmpty(t, env.Resources.Items()) + + env.Resources.VisitMetaObject(func(res metav1.Object) { + if withOwnerRef { + assert.NotEmpty(t, res.GetOwnerReferences()) + } else { + assert.Empty(t, res.GetOwnerReferences()) + } + + ValidateLabelsAndAnnotations(t, res) + }) + + deployments := make([]*appsv1.Deployment, 0) + env.Resources.VisitDeployment(func(deployment *appsv1.Deployment) { + deployments = append(deployments, deployment) + }) + + assert.Len(t, deployments, 1) + ValidateLabelsAndAnnotations(t, &deployments[0].Spec.Template) +} + +func ValidateLabelsAndAnnotations(t *testing.T, res metav1.Object) { + assert.Contains(t, res.GetLabels(), "com.mycompany/mylabel1") + assert.Equal(t, "myvalue1", res.GetLabels()["com.mycompany/mylabel1"]) + + assert.NotContains(t, res.GetLabels(), "com.mycompany/mylabel2") + + assert.Contains(t, res.GetAnnotations(), "com.mycompany/myannotation2") + assert.Equal(t, "myannotation2", res.GetAnnotations()["com.mycompany/myannotation2"]) }