From 9c501ffe875e7fad119cb662c6fc5ba233246adb Mon Sep 17 00:00:00 2001 From: sg Date: Mon, 19 Aug 2024 21:34:37 +0100 Subject: [PATCH] iclose #307 by making addanchors and add env vars idempotent --- pkg/components/package.go | 99 +++++++++++++++++++++++--------- pkg/components/package_test.go | 100 +++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+), 26 deletions(-) diff --git a/pkg/components/package.go b/pkg/components/package.go index 867543011..485c938a1 100644 --- a/pkg/components/package.go +++ b/pkg/components/package.go @@ -216,7 +216,11 @@ func addAnchorResult(task *tektonv1beta1api.Task) error { if hasLabel { return nil } - + for _, step := range task.Spec.Steps { + if step.Name == "anchor" { + return nil + } + } task.Spec.Results = append(task.Spec.Results, tektonv1beta1api.TaskResult{ Name: "anchor", Description: "An anchor to allow other tasks to depend on this task.", @@ -248,7 +252,6 @@ func addAnchorParameter(task *tektonv1beta1api.Task) error { return nil } } - task.Spec.Params = append(task.Spec.Params, tektonv1beta1api.ParamSpec{ Name: "anchors", Description: "A list of tasks that this task depends on", @@ -272,39 +275,83 @@ func addEnvVarsToTask(task *tektonv1beta1api.Task) error { if componentType != Producer { return nil } + scanIDFound := false + scanStartTimeFound := false + scanTagsFound := false - task.Spec.Params = append(task.Spec.Params, tektonv1beta1api.ParamSpecs{ - { - Name: "dracon_scan_id", - Type: tektonv1beta1api.ParamTypeString, - }, - { - Name: "dracon_scan_start_time", - Type: tektonv1beta1api.ParamTypeString, - }, - { - Name: "dracon_scan_tags", - Type: tektonv1beta1api.ParamTypeString, - }, - }...) - - for i, step := range task.Spec.Steps { - step.Env = append(step.Env, []corev1.EnvVar{ + for _, param := range task.Spec.Params { + if param.Name == "dracon_scan_id" { + scanIDFound = true + } else if param.Name == "dracon_scan_start_time" { + scanStartTimeFound = true + } else if param.Name == "dracon_scan_tags" { + scanTagsFound = true + } + } + if !scanIDFound { + task.Spec.Params = append(task.Spec.Params, tektonv1beta1api.ParamSpecs{ { - Name: "DRACON_SCAN_TIME", - Value: "$(params.dracon_scan_start_time)", + Name: "dracon_scan_id", + Type: tektonv1beta1api.ParamTypeString, }, + }...) + } + if !scanStartTimeFound { + task.Spec.Params = append(task.Spec.Params, tektonv1beta1api.ParamSpecs{ { - Name: "DRACON_SCAN_ID", - Value: "$(params.dracon_scan_id)", + Name: "dracon_scan_start_time", + Type: tektonv1beta1api.ParamTypeString, }, + }...) + } + if !scanTagsFound { + task.Spec.Params = append(task.Spec.Params, tektonv1beta1api.ParamSpecs{ { - Name: "DRACON_SCAN_TAGS", - Value: "$(params.dracon_scan_tags)", + Name: "dracon_scan_tags", + Type: tektonv1beta1api.ParamTypeString, }, }...) - task.Spec.Steps[i] = step } + scanIDFound = false + scanStartTimeFound = false + scanTagsFound = false + for i, step := range task.Spec.Steps { + for _, envVar := range step.Env { + if envVar.Name == "DRACON_SCAN_TIME" { + scanStartTimeFound = true + } else if envVar.Name == "DRACON_SCAN_ID" { + scanIDFound = true + } else if envVar.Name == "DRACON_SCAN_TAGS" { + scanTagsFound = true + } + } + if !scanStartTimeFound { + step.Env = append(step.Env, []corev1.EnvVar{ + { + Name: "DRACON_SCAN_TIME", + Value: "$(params.dracon_scan_start_time)", + }, + }...) + } + if !scanIDFound { + step.Env = append(step.Env, []corev1.EnvVar{ + { + Name: "DRACON_SCAN_ID", + Value: "$(params.dracon_scan_id)", + }, + }...) + } + if !scanTagsFound { + step.Env = append(step.Env, []corev1.EnvVar{ + { + Name: "DRACON_SCAN_TAGS", + Value: "$(params.dracon_scan_tags)", + }, + }...) + } + + task.Spec.Steps[i] = step + } return nil } diff --git a/pkg/components/package_test.go b/pkg/components/package_test.go index a99f0345d..c99f85f53 100644 --- a/pkg/components/package_test.go +++ b/pkg/components/package_test.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "path" + "slices" "strings" "testing" @@ -115,3 +116,102 @@ version: %s require.Equal(t, "anchor", task.Spec.Steps[len(task.Spec.Steps)-1].Name, "task %s has no anchor step", task.Name) } } + +func TestProcessTasksAnchorsEnvExist(t *testing.T) { + taskList, err := LoadTasks( + context.Background(), + []string{ + "testdata/base/task.yaml", + "testdata/sources/git/task.yaml", + "testdata/producers/cdxgen/task.yaml", + "testdata/producers/aggregator/task.yaml", + "testdata/enrichers/aggregator/task.yaml", + "testdata/consumers/arangodb/task.yaml", + }, + ) + require.NoError(t, err) + + // add anchors and env vars once + require.NoError(t, ProcessTasks(taskList...)) + + // ensure anchors have been added once + requireAnchors(t, taskList) + + // ensure envvars have been added once + requireEnvVars(t, taskList) + + // add anchors and env vars again + require.NoError(t, ProcessTasks(taskList...)) + + // ensure anchors have been added once + requireAnchors(t, taskList) + requireEnvVars(t, taskList) +} + +//revive:disable:cyclomatic High complexity score but easy to understand +//revive:disable:cognitive-complexity High complexity score but easy to understand +func requireAnchors(t *testing.T, taskList []*tektonv1beta1api.Task) { + for _, task := range taskList { + require.NotEmpty(t, task.Spec.Steps) + if strings.Contains(task.Name, "base") || strings.Contains(task.Name, "git") { // base and git tasks have no anchors + continue + } + + anchorParamNames := []string{} + for _, param := range task.Spec.Params { + if param.Name == "anchors" { + anchorParamNames = append(anchorParamNames, "anchors") + } + } + + anchorNames := []string{} + for _, step := range task.Spec.Steps { + if step.Name == "anchor" { + anchorNames = append(anchorNames, "anchor") + } + } + anchorResultNames := []string{} + for _, result := range task.Spec.Results { + if result.Name == "anchor" { + anchorResultNames = append(anchorResultNames, "anchor") + } + } + require.Equal(t, len(anchorParamNames), 1) + + if strings.Contains(task.Name, "consumer") { + continue // consumers have no anchor steps + } + require.Equal(t, len(anchorNames), 1) + require.Equal(t, len(anchorResultNames), 1) + } +} + +//revive:disable:cyclomatic High complexity score but easy to understand +//revive:disable:cognitive-complexity High complexity score but easy to understand +func requireEnvVars(t *testing.T, taskList []*tektonv1beta1api.Task) { + envVars := []string{"DRACON_SCAN_TIME", "DRACON_SCAN_ID", "DRACON_SCAN_TAGS"} + params := []string{"dracon_scan_id", "dracon_scan_start_time", "dracon_scan_tags"} + for _, task := range taskList { + taskParams := []string{} + if !strings.Contains(task.Name, "producer") || strings.Contains(task.Name, "aggregator") { // env vars are for producers only + continue + } + for _, p := range task.Spec.Params { + if slices.Contains(params, p.Name) { + taskParams = append(taskParams, p.Name) + } + } + + require.Equalf(t, len(taskParams), len(params), "task %s has missing params", task.Name) + for _, step := range task.Spec.Steps { + require.NotEmptyf(t, step.Env, "task %s has no env vars", task.Name) + stepEnvVars := []string{} + for _, env := range step.Env { + if slices.Contains(envVars, env.Name) { + stepEnvVars = append(stepEnvVars, env.Name) + } + } + require.Equalf(t, len(envVars), len(stepEnvVars), "task %s has env vars %#v", task.Name, stepEnvVars) + } + } +}