From 56c2eaf4357ccc380572f97c259ee25ad02b45b8 Mon Sep 17 00:00:00 2001 From: Karolis Rusenas Date: Wed, 7 Nov 2018 23:16:09 +0000 Subject: [PATCH 1/5] checking trigger type and policy in the annotations as well --- internal/policy/policy.go | 13 ++++++++---- internal/policy/policy_test.go | 36 ++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/internal/policy/policy.go b/internal/policy/policy.go index 6e645da1e..01b3ae036 100644 --- a/internal/policy/policy.go +++ b/internal/policy/policy.go @@ -30,15 +30,20 @@ func (np *NilPolicy) ShouldUpdate(c, n string) (bool, error) { return false, nil func (np *NilPolicy) Name() string { return "nil policy" } func (np *NilPolicy) Type() PolicyType { return PolicyTypeNone } -// GetPolicyFromLabels - gets policy from k8s labels -func GetPolicyFromLabels(labels map[string]string) Policy { +// GetPolicyFromLabelsOrAnnotations - gets policy from k8s labels or annotations +func GetPolicyFromLabelsOrAnnotations(labels map[string]string, annotations map[string]string) Policy { - policyName, ok := getPolicyFromLabels(labels) + policyNameA, ok := getPolicyFromLabels(annotations) + if ok { + return GetPolicy(policyNameA, &Options{MatchTag: getMatchTag(annotations)}) + } + + policyNameL, ok := getPolicyFromLabels(labels) if !ok { return &NilPolicy{} } - return GetPolicy(policyName, &Options{MatchTag: getMatchTag(labels)}) + return GetPolicy(policyNameL, &Options{MatchTag: getMatchTag(labels)}) // switch policyName { // case "all", "major", "minor", "patch": diff --git a/internal/policy/policy_test.go b/internal/policy/policy_test.go index 33e8a33e3..477f024c3 100644 --- a/internal/policy/policy_test.go +++ b/internal/policy/policy_test.go @@ -91,3 +91,39 @@ func TestGetPolicy(t *testing.T) { }) } } + +func TestGetPolicyFromLabelsOrAnnotations(t *testing.T) { + type args struct { + labels map[string]string + annotations map[string]string + } + tests := []struct { + name string + args args + want Policy + }{ + { + name: "annotations policy", + args: args{ + labels: map[string]string{"foo": "bar"}, + annotations: map[string]string{types.KeelPolicyLabel: "all"}, + }, + want: NewSemverPolicy(SemverPolicyTypeAll), + }, + { + name: "annotations overides labels", + args: args{ + labels: map[string]string{types.KeelPolicyLabel: "patch"}, + annotations: map[string]string{types.KeelPolicyLabel: "all"}, + }, + want: NewSemverPolicy(SemverPolicyTypeAll), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := GetPolicyFromLabelsOrAnnotations(tt.args.labels, tt.args.annotations); !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetPolicyFromLabelsOrAnnotations() = %v, want %v", got, tt.want) + } + }) + } +} From e2507985dce80112a220e9ee70456bc9e3f231bb Mon Sep 17 00:00:00 2001 From: Karolis Rusenas Date: Wed, 7 Nov 2018 23:16:23 +0000 Subject: [PATCH 2/5] passing in annotations --- provider/kubernetes/kubernetes.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/provider/kubernetes/kubernetes.go b/provider/kubernetes/kubernetes.go index ba5c801cb..52483d8e3 100644 --- a/provider/kubernetes/kubernetes.go +++ b/provider/kubernetes/kubernetes.go @@ -131,14 +131,14 @@ func (p *Provider) TrackedImages() ([]*types.TrackedImage, error) { for _, gr := range p.cache.Values() { labels := gr.GetLabels() + annotations := gr.GetAnnotations() // ignoring unlabelled deployments - plc := policy.GetPolicyFromLabels(labels) + plc := policy.GetPolicyFromLabelsOrAnnotations(labels, annotations) if plc.Type() == policy.PolicyTypeNone { continue } - annotations := gr.GetAnnotations() schedule, ok := annotations[types.KeelPollScheduleAnnotation] if ok { _, err := cron.Parse(schedule) @@ -156,7 +156,7 @@ func (p *Provider) TrackedImages() ([]*types.TrackedImage, error) { } // trigger type, we only care for "poll" type triggers - trigger := policies.GetTriggerPolicy(labels) + trigger := policies.GetTriggerPolicy(labels, annotations) secrets := gr.GetImagePullSecrets() images := gr.GetImages() for _, img := range images { @@ -343,10 +343,11 @@ func (p *Provider) createUpdatePlans(repo *types.Repository) ([]*UpdatePlan, err for _, resource := range p.cache.Values() { labels := resource.GetLabels() + annotations := resource.GetAnnotations() - plc := policy.GetPolicyFromLabels(labels) + plc := policy.GetPolicyFromLabelsOrAnnotations(labels, annotations) if plc.Type() == policy.PolicyTypeNone { - log.Debugf("no policy defined, skipping: %s, labels: %s", resource.Identifier, labels) + log.Debugf("no policy defined, skipping: %s, labels: %s, annotations: %s", resource.Identifier, labels, annotations) continue } From e4027db612c16219b0dce13c55e7a34754882bba Mon Sep 17 00:00:00 2001 From: Karolis Rusenas Date: Wed, 7 Nov 2018 23:16:48 +0000 Subject: [PATCH 3/5] getting impacted deployments, policy in annotations --- provider/kubernetes/kubernetes_test.go | 96 ++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/provider/kubernetes/kubernetes_test.go b/provider/kubernetes/kubernetes_test.go index b06ba1b98..a39581703 100644 --- a/provider/kubernetes/kubernetes_test.go +++ b/provider/kubernetes/kubernetes_test.go @@ -266,6 +266,102 @@ func TestGetImpacted(t *testing.T) { t.Errorf("couldn't find expected deployment in impacted deployment list") } +} +func TestGetImpactedPolicyAnnotations(t *testing.T) { + fp := &fakeImplementer{} + fp.namespaces = &v1.NamespaceList{ + Items: []v1.Namespace{ + v1.Namespace{ + meta_v1.TypeMeta{}, + meta_v1.ObjectMeta{Name: "xxxx"}, + v1.NamespaceSpec{}, + v1.NamespaceStatus{}, + }, + }, + } + + deps := []*apps_v1.Deployment{ + { + meta_v1.TypeMeta{}, + meta_v1.ObjectMeta{ + Name: "dep-1", + Namespace: "xxxx", + Annotations: map[string]string{types.KeelPolicyLabel: "all"}, + Labels: map[string]string{"foo": "all"}, + }, + apps_v1.DeploymentSpec{ + Template: v1.PodTemplateSpec{ + Spec: v1.PodSpec{ + Containers: []v1.Container{ + v1.Container{ + Image: "gcr.io/v2-namespace/hello-world:1.1.1", + }, + }, + }, + }, + }, + apps_v1.DeploymentStatus{}, + }, + { + meta_v1.TypeMeta{}, + meta_v1.ObjectMeta{ + Name: "dep-2", + Namespace: "xxxx", + Labels: map[string]string{"whatever": "all"}, + }, + apps_v1.DeploymentSpec{ + Template: v1.PodTemplateSpec{ + Spec: v1.PodSpec{ + Containers: []v1.Container{ + v1.Container{ + Image: "gcr.io/v2-namespace/hello-world:1.1.1", + }, + }, + }, + }, + }, + apps_v1.DeploymentStatus{}, + }, + } + + grs := MustParseGRS(deps) + grc := &k8s.GenericResourceCache{} + grc.Add(grs...) + + provider, err := NewProvider(fp, &fakeSender{}, approver(), grc) + if err != nil { + t.Fatalf("failed to get provider: %s", err) + } + + // creating "new version" event + repo := &types.Repository{ + Name: "gcr.io/v2-namespace/hello-world", + Tag: "1.1.2", + } + + plans, err := provider.createUpdatePlans(repo) + if err != nil { + t.Errorf("failed to get deployments: %s", err) + } + + if len(plans) != 1 { + t.Fatalf("expected to find 1 deployment update plan but found %d", len(plans)) + } + + found := false + for _, c := range plans[0].Resource.Containers() { + + containerImageName := versionreg.ReplaceAllString(c.Image, "") + + if containerImageName == repo.Name { + found = true + } + } + + if !found { + t.Errorf("couldn't find expected deployment in impacted deployment list") + } + } func TestPrereleaseGetImpactedA(t *testing.T) { // test scenario when we have two deployments, one with pre-release tag From 60988005cce37a9db5e527c26f8b058183d0c7d7 Mon Sep 17 00:00:00 2001 From: Karolis Rusenas Date: Wed, 7 Nov 2018 23:16:57 +0000 Subject: [PATCH 4/5] trigger type from annotations --- util/policies/policies.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/util/policies/policies.go b/util/policies/policies.go index e2bb81dec..379260ac9 100644 --- a/util/policies/policies.go +++ b/util/policies/policies.go @@ -6,10 +6,18 @@ import ( // GetTriggerPolicy - checks for trigger label, if not set - returns // default trigger type -func GetTriggerPolicy(labels map[string]string) types.TriggerType { +func GetTriggerPolicy(labels map[string]string, annotations map[string]string) types.TriggerType { + + triggerAnn, ok := annotations[types.KeelTriggerLabel] + if ok { + return types.ParseTrigger(triggerAnn) + } + + // checking labels trigger, ok := labels[types.KeelTriggerLabel] if ok { return types.ParseTrigger(trigger) } + return types.TriggerTypeDefault } From 27814f2b5812fe42a3b97bd6cb9d0a82a664403e Mon Sep 17 00:00:00 2001 From: Karolis Rusenas Date: Wed, 7 Nov 2018 23:27:05 +0000 Subject: [PATCH 5/5] #295 don't error on each helm release without the keel cfg, more info if policy is unknown --- internal/policy/policy.go | 2 +- provider/helm/helm.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/policy/policy.go b/internal/policy/policy.go index 01b3ae036..969c5d4ea 100644 --- a/internal/policy/policy.go +++ b/internal/policy/policy.go @@ -94,7 +94,7 @@ func GetPolicy(policyName string, options *Options) Policy { return NewForcePolicy(options.MatchTag) } - log.Infof("unknown policy '%s'", policyName) + log.Infof("policy.GetPolicy: unknown policy '%s', please check your configuration", policyName) return &NilPolicy{} } diff --git a/provider/helm/helm.go b/provider/helm/helm.go index eb243ac85..23d9f78e9 100644 --- a/provider/helm/helm.go +++ b/provider/helm/helm.go @@ -187,7 +187,7 @@ func (p *Provider) TrackedImages() ([]*types.TrackedImage, error) { "error": err, "release": release.Name, "namespace": release.Namespace, - }).Error("provider.helm: failed to get config for release") + }).Debug("provider.helm: failed to get config for release") continue }