Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(operator): propagate KeptnTaskDefinition labels and annotations to Job Pods #1283

Merged
merged 3 commits into from
Apr 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions operator/apis/lifecycle/v1alpha3/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,16 @@ func GenerateEvaluationName(checkType CheckType, evalName string) string {
randomId := rand.Intn(99_999-10_000) + 10000
return fmt.Sprintf("%s-%s-%d", checkType, TruncateString(evalName, 27), randomId)
}

// MergeMaps merges two maps into a new map. If a key exists in both maps, the
// value of the second map is picked.
func MergeMaps(m1 map[string]string, m2 map[string]string) map[string]string {
odubajDT marked this conversation as resolved.
Show resolved Hide resolved
merged := make(map[string]string, len(m1)+len(m2))
for key, value := range m1 {
merged[key] = value
}
for key, value := range m2 {
merged[key] = value
}
return merged
}
57 changes: 57 additions & 0 deletions operator/apis/lifecycle/v1alpha3/common/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,3 +331,60 @@ func Test_GenerateEvaluationName(t *testing.T) {
})
}
}

func Test_MergeMaps(t *testing.T) {
tests := []struct {
In1 map[string]string
In2 map[string]string
Want map[string]string
}{
{
In1: nil,
In2: nil,
Want: map[string]string{},
},
{
In1: nil,
In2: map[string]string{
"ll1": "ll2",
"ll3": "ll4",
},
Want: map[string]string{
"ll1": "ll2",
"ll3": "ll4",
},
},
{
In1: map[string]string{
"ll1": "ll2",
"ll3": "ll4",
},
In2: nil,
Want: map[string]string{
"ll1": "ll2",
"ll3": "ll4",
},
},
{
In1: map[string]string{
"ll1": "ll2",
"ll3": "ll4",
},
In2: map[string]string{
"ll5": "ll6",
"ll7": "ll8",
},
Want: map[string]string{
"ll1": "ll2",
"ll3": "ll4",
"ll5": "ll6",
"ll7": "ll8",
},
},
}
for _, tt := range tests {
t.Run("", func(t *testing.T) {
require.Equal(t, MergeMaps(tt.In1, tt.In2), tt.Want)
})
}
}
14 changes: 14 additions & 0 deletions operator/apis/lifecycle/v1alpha3/keptnappversion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,12 @@ func TestKeptnAppVersion(t *testing.T) {
task := app.GenerateTask(KeptnTaskDefinition{
ObjectMeta: v1.ObjectMeta{
Name: "task-def",
Labels: map[string]string{
"label1": "label2",
},
Annotations: map[string]string{
"annotation1": "annotation2",
},
},
Spec: KeptnTaskDefinitionSpec{
Timeout: v1.Duration{
Expand All @@ -203,6 +209,14 @@ func TestKeptnAppVersion(t *testing.T) {
Retries: &retries,
}, task.Spec)

require.Equal(t, map[string]string{
"label1": "label2",
}, task.Labels)

require.Equal(t, map[string]string{
"annotation1": "annotation2",
}, task.Annotations)

evaluation := app.GenerateEvaluation(KeptnEvaluationDefinition{
ObjectMeta: v1.ObjectMeta{
Name: "eval-def",
Expand Down
6 changes: 4 additions & 2 deletions operator/apis/lifecycle/v1alpha3/keptnappversion_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,8 +313,10 @@ func (a KeptnAppVersion) GetVersion() string {
func (a KeptnAppVersion) GenerateTask(taskDefinition KeptnTaskDefinition, checkType common.CheckType) KeptnTask {
return KeptnTask{
ObjectMeta: metav1.ObjectMeta{
Name: common.GenerateTaskName(checkType, taskDefinition.Name),
Namespace: a.Namespace,
Name: common.GenerateTaskName(checkType, taskDefinition.Name),
Namespace: a.Namespace,
Labels: taskDefinition.Labels,
Annotations: taskDefinition.Annotations,
},
Spec: KeptnTaskSpec{
AppVersion: a.GetVersion(),
Expand Down
14 changes: 14 additions & 0 deletions operator/apis/lifecycle/v1alpha3/keptntask_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ func TestKeptnTask(t *testing.T) {
task := &KeptnTask{
ObjectMeta: metav1.ObjectMeta{
Name: "task",
Labels: map[string]string{
"label1": "label2",
},
Annotations: map[string]string{
"annotation1": "annotation2",
},
},
Spec: KeptnTaskSpec{
AppName: "app",
Expand All @@ -33,6 +39,12 @@ func TestKeptnTask(t *testing.T) {
require.Equal(t, KeptnTask{
ObjectMeta: metav1.ObjectMeta{
Name: "task",
Labels: map[string]string{
"label1": "label2",
},
Annotations: map[string]string{
"annotation1": "annotation2",
},
},
Spec: KeptnTaskSpec{
AppName: "app",
Expand Down Expand Up @@ -83,6 +95,7 @@ func TestKeptnTask(t *testing.T) {
"keptn.sh/app": "app",
"keptn.sh/task-name": "task",
"keptn.sh/version": "appversion",
"label1": "label2",
}, task.CreateKeptnLabels())

task.Spec.Workload = "workload"
Expand All @@ -93,6 +106,7 @@ func TestKeptnTask(t *testing.T) {
"keptn.sh/workload": "workload",
"keptn.sh/task-name": "task",
"keptn.sh/version": "workloadversion",
"label1": "label2",
}, task.CreateKeptnLabels())

require.Equal(t, []attribute.KeyValue{
Expand Down
8 changes: 4 additions & 4 deletions operator/apis/lifecycle/v1alpha3/keptntask_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,18 +168,18 @@ func (t KeptnTask) SetSpanAttributes(span trace.Span) {

func (t KeptnTask) CreateKeptnLabels() map[string]string {
if t.Spec.Workload != "" {
return map[string]string{
return common.MergeMaps(t.Labels, map[string]string{
common.AppAnnotation: t.Spec.AppName,
common.WorkloadAnnotation: t.Spec.Workload,
common.VersionAnnotation: t.Spec.WorkloadVersion,
common.TaskNameAnnotation: t.Name,
}
})
}
return map[string]string{
return common.MergeMaps(t.Labels, map[string]string{
common.AppAnnotation: t.Spec.AppName,
common.VersionAnnotation: t.Spec.AppVersion,
common.TaskNameAnnotation: t.Name,
}
})
}

func (t KeptnTask) GetSpanAttributes() []attribute.KeyValue {
Expand Down
14 changes: 14 additions & 0 deletions operator/apis/lifecycle/v1alpha3/keptnworkloadinstance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,12 @@ func TestKeptnWorkloadInstance(t *testing.T) {
task := workload.GenerateTask(KeptnTaskDefinition{
ObjectMeta: v1.ObjectMeta{
Name: "task-def",
Labels: map[string]string{
"label1": "label2",
},
Annotations: map[string]string{
"annotation1": "annotation2",
},
},
Spec: KeptnTaskDefinitionSpec{
Timeout: v1.Duration{
Expand All @@ -208,6 +214,14 @@ func TestKeptnWorkloadInstance(t *testing.T) {
Retries: &retries,
}, task.Spec)

require.Equal(t, map[string]string{
"label1": "label2",
}, task.Labels)

require.Equal(t, map[string]string{
"annotation1": "annotation2",
}, task.Annotations)

evaluation := workload.GenerateEvaluation(KeptnEvaluationDefinition{
ObjectMeta: v1.ObjectMeta{
Name: "eval-def",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,8 +321,10 @@ func (w KeptnWorkloadInstance) GetVersion() string {
func (w KeptnWorkloadInstance) GenerateTask(taskDefinition KeptnTaskDefinition, checkType common.CheckType) KeptnTask {
return KeptnTask{
ObjectMeta: metav1.ObjectMeta{
Name: common.GenerateTaskName(checkType, taskDefinition.Name),
Namespace: w.Namespace,
Name: common.GenerateTaskName(checkType, taskDefinition.Name),
Namespace: w.Namespace,
Labels: taskDefinition.Labels,
Annotations: taskDefinition.Annotations,
},
Spec: KeptnTaskSpec{
AppName: w.GetAppName(),
Expand Down
11 changes: 8 additions & 3 deletions operator/controllers/lifecycle/keptntask/function_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,17 @@ func (r *KeptnTaskReconciler) generateFunctionJob(task *klcv1alpha3.KeptnTask, p
jobId := fmt.Sprintf("klc-%s-%d", apicommon.TruncateString(task.Name, apicommon.MaxTaskNameLength), randomId)
job := &batchv1.Job{
ObjectMeta: metav1.ObjectMeta{
Name: jobId,
Namespace: task.Namespace,
Labels: task.CreateKeptnLabels(),
Name: jobId,
Namespace: task.Namespace,
Labels: task.CreateKeptnLabels(),
Annotations: task.Annotations,
},
Spec: batchv1.JobSpec{
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: task.Labels,
Annotations: task.Annotations,
},
Spec: corev1.PodSpec{
RestartPolicy: "OnFailure",
},
Expand Down
22 changes: 22 additions & 0 deletions operator/controllers/lifecycle/keptntask/job_utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,16 @@ func TestKeptnTaskReconciler_createJob(t *testing.T) {
require.NotEmpty(t, resultingJob.OwnerReferences)
require.Len(t, resultingJob.Spec.Template.Spec.Containers, 1)
require.Len(t, resultingJob.Spec.Template.Spec.Containers[0].Env, 4)
require.Equal(t, map[string]string{
"label1": "label2",
"keptn.sh/app": "my-app",
"keptn.sh/task-name": "my-task",
"keptn.sh/version": "",
"keptn.sh/workload": "my-workload",
}, resultingJob.Labels)
require.Equal(t, map[string]string{
"annotation1": "annotation2",
}, resultingJob.Annotations)
}

func TestKeptnTaskReconciler_updateJob(t *testing.T) {
Expand Down Expand Up @@ -158,6 +168,12 @@ func makeTask(name, namespace string, taskDefinitionName string) *klcv1alpha3.Ke
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Labels: map[string]string{
"label1": "label2",
},
Annotations: map[string]string{
"annotation1": "annotation2",
},
},
Spec: klcv1alpha3.KeptnTaskSpec{
Workload: "my-workload",
Expand All @@ -173,6 +189,12 @@ func makeTaskDefinitionWithConfigmapRef(name, namespace, configMapName string) *
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Labels: map[string]string{
"label1": "label2",
},
Annotations: map[string]string{
"annotation1": "annotation2",
},
},
Spec: klcv1alpha3.KeptnTaskDefinitionSpec{
Function: klcv1alpha3.FunctionSpec{
Expand Down
52 changes: 52 additions & 0 deletions operator/test/component/task/task_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,57 @@ var _ = Describe("Task", Ordered, func() {
g.Expect(task.Status.Status).To(Equal(apicommon.StateFailed))
}, "10s").Should(Succeed())
})
It("should propagate labels and annotations to the job and job pod", func() {
By("Verifying that a job has been created")

Eventually(func(g Gomega) {
err := k8sClient.Get(context.TODO(), types.NamespacedName{
Namespace: namespace,
Name: task.Name,
}, task)
g.Expect(err).To(BeNil())
g.Expect(task.Status.JobName).To(Not(BeEmpty()))
}, "10s").Should(Succeed())

createdJob := &batchv1.Job{}

err := k8sClient.Get(context.TODO(), types.NamespacedName{
Namespace: namespace,
Name: task.Status.JobName,
}, createdJob)

Expect(err).To(BeNil())

Expect(createdJob.Annotations).To(Equal(map[string]string{
"annotation1": "annotation2",
}))

Expect(createdJob.Labels).To(Equal(map[string]string{
"keptn.sh/task-name": task.Name,
"keptn.sh/version": "",
"keptn.sh/workload": "my-workload",
"label1": "label2",
"keptn.sh/app": "my-app",
}))

val, ok := createdJob.Spec.Template.Labels["label1"]
Expect(ok && val == "label2").To(BeTrue())

val, ok = createdJob.Spec.Template.Annotations["annotation1"]
Expect(ok && val == "annotation2").To(BeTrue())
})
AfterEach(func() {
err := k8sClient.Delete(context.TODO(), taskDefinition)
common.LogErrorIfPresent(err)
err = k8sClient.Delete(context.TODO(), task)
common.LogErrorIfPresent(err)
err = k8sClient.Delete(context.TODO(), &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: taskDefinition.Status.Function.ConfigMap,
Namespace: namespace,
},
})
common.LogErrorIfPresent(err)
})
})
})
Expand All @@ -94,6 +140,12 @@ func makeTask(name string, namespace, taskDefinitionName string) *klcv1alpha3.Ke
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Labels: map[string]string{
"label1": "label2",
},
Annotations: map[string]string{
"annotation1": "annotation2",
},
},
Spec: klcv1alpha3.KeptnTaskSpec{
Workload: "my-workload",
Expand Down