From a605dfbcd27bf541d0ffe84a0b0c77c1c9f95016 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Thu, 8 Aug 2024 15:30:34 +0300 Subject: [PATCH] feat: pass execution tags Signed-off-by: Vladislav Sukhin --- .../testworkflow-toolkit/commands/execute.go | 12 +++++++++ cmd/tcl/testworkflow-toolkit/spawn/utils.go | 1 + cmd/testworkflow-toolkit/env/config.go | 5 ++++ .../testworkflowexecutor/executor.go | 27 +++++++++++++++++++ .../testworkflowprocessor/stage/container.go | 1 + .../testworkflowresolver/apply.go | 1 + .../testworkflowresolver/merge.go | 18 +++++++++++++ 7 files changed, 65 insertions(+) diff --git a/cmd/tcl/testworkflow-toolkit/commands/execute.go b/cmd/tcl/testworkflow-toolkit/commands/execute.go index fd398f8fc46..c2d60e11460 100644 --- a/cmd/tcl/testworkflow-toolkit/commands/execute.go +++ b/cmd/tcl/testworkflow-toolkit/commands/execute.go @@ -9,6 +9,7 @@ package commands import ( + "encoding/base64" "encoding/json" "fmt" "os" @@ -151,10 +152,21 @@ func buildWorkflowExecution(workflow testworkflowsv1.StepExecuteWorkflow, async return func() (err error) { c := env.Testkube() + var tags map[string]string + if tagsData := env.ExecutionTags(); tagsData != "" { + data, err := base64.StdEncoding.DecodeString(tagsData) + if err != nil { + ui.Errf("failed to decode tags: %s: %s", workflow.Name, err.Error()) + } else if err = json.Unmarshal(data, &tags); err != nil { + ui.Errf("failed to unmarshal tags: %s: %s", workflow.Name, err.Error()) + } + } + exec, err := c.ExecuteTestWorkflow(workflow.Name, testkube.TestWorkflowExecutionRequest{ Name: workflow.ExecutionName, Config: testworkflows.MapConfigValueKubeToAPI(workflow.Config), DisableWebhooks: env.ExecutionDisableWebhooks(), + Tags: tags, }) execName := exec.Name if err != nil { diff --git a/cmd/tcl/testworkflow-toolkit/spawn/utils.go b/cmd/tcl/testworkflow-toolkit/spawn/utils.go index 83da8882b48..3137f3b35ba 100644 --- a/cmd/tcl/testworkflow-toolkit/spawn/utils.go +++ b/cmd/tcl/testworkflow-toolkit/spawn/utils.go @@ -204,6 +204,7 @@ func CreateExecutionMachine(prefix string, index int64) (string, expressions.Mac "number": env.ExecutionNumber(), "scheduledAt": env.ExecutionScheduledAt().UTC().Format(constants.RFC3339Millis), "disableWebhooks": env.ExecutionDisableWebhooks(), + "tags": env.ExecutionTags(), }) } diff --git a/cmd/testworkflow-toolkit/env/config.go b/cmd/testworkflow-toolkit/env/config.go index 02bdff02e42..519a8d80d18 100644 --- a/cmd/testworkflow-toolkit/env/config.go +++ b/cmd/testworkflow-toolkit/env/config.go @@ -47,6 +47,7 @@ type envExecutionConfig struct { RootResourceId string `envconfig:"TK_EXR"` FSPrefix string `envconfig:"TK_FS"` DisableWebhooks bool `envconfig:"TK_DWH"` + Tags string `envconfig:"TK_TAG"` } type envSystemConfig struct { @@ -157,3 +158,7 @@ func ExecutionDisableWebhooks() bool { func JUnitParserEnabled() bool { return Config().Features.EnableJUnitParser } + +func ExecutionTags() string { + return Config().Execution.Tags +} diff --git a/pkg/testworkflows/testworkflowexecutor/executor.go b/pkg/testworkflows/testworkflowexecutor/executor.go index 85d4d042d60..dcd0936e471 100644 --- a/pkg/testworkflows/testworkflowexecutor/executor.go +++ b/pkg/testworkflows/testworkflowexecutor/executor.go @@ -3,8 +3,11 @@ package testworkflowexecutor import ( "bufio" "context" + "encoding/base64" + "encoding/json" "fmt" "io" + "maps" "os" "strconv" "sync" @@ -466,6 +469,7 @@ func (e *executor) Execute(ctx context.Context, workflow testworkflowsv1.TestWor "number": "1", "scheduledAt": now.UTC().Format(constants.RFC3339Millis), "disableWebhooks": request.DisableWebhooks, + "tags": "", }) // Preserve resolved TestWorkflow @@ -504,6 +508,27 @@ func (e *executor) Execute(ctx context.Context, workflow testworkflowsv1.TestWor return execution, errors.Wrap(err, "execution name already exists") } + var tags map[string]string + if workflow.Spec.Execution != nil { + tags = workflow.Spec.Execution.Tags + if request.Tags != nil { + if tags == nil { + tags = make(map[string]string) + } + + maps.Copy(tags, request.Tags) + } + } + + var tagsData string + if tags != nil { + if data, err := json.Marshal(tags); err != nil { + log.DefaultLogger.Errorw("failed to marshal tags", "id", id, "error", err) + } else { + tagsData = base64.StdEncoding.EncodeToString(data) + } + } + // Build machine with actual execution data executionMachine := expressions.NewMachine().Register("execution", map[string]interface{}{ "id": id, @@ -511,6 +536,7 @@ func (e *executor) Execute(ctx context.Context, workflow testworkflowsv1.TestWor "number": number, "scheduledAt": now.UTC().Format(constants.RFC3339Millis), "disableWebhooks": request.DisableWebhooks, + "tags": tagsData, }) // Process the TestWorkflow @@ -542,6 +568,7 @@ func (e *executor) Execute(ctx context.Context, workflow testworkflowsv1.TestWor ResolvedWorkflow: testworkflowmappers.MapKubeToAPI(resolvedWorkflow), TestWorkflowExecutionName: testWorkflowExecutionName, DisableWebhooks: request.DisableWebhooks, + Tags: tags, } err = e.repository.Insert(ctx, execution) if err != nil { diff --git a/pkg/testworkflows/testworkflowprocessor/stage/container.go b/pkg/testworkflows/testworkflowprocessor/stage/container.go index d316c5d8810..a7367a3cdcc 100644 --- a/pkg/testworkflows/testworkflowprocessor/stage/container.go +++ b/pkg/testworkflows/testworkflowprocessor/stage/container.go @@ -459,6 +459,7 @@ func (c *container) EnableToolkit(ref string) Container { "TK_EXC": "{{execution.number}}", "TK_EXS": "{{execution.scheduledAt}}", "TK_DWH": "{{execution.disableWebhooks}}", + "TK_TAG": "{{execution.tags}}", "TK_EXI": "{{resource.id}}", "TK_EXR": "{{resource.root}}", "TK_FS": "{{resource.fsPrefix}}", diff --git a/pkg/testworkflows/testworkflowresolver/apply.go b/pkg/testworkflows/testworkflowresolver/apply.go index db9abf70603..31293719d68 100644 --- a/pkg/testworkflows/testworkflowresolver/apply.go +++ b/pkg/testworkflows/testworkflowresolver/apply.go @@ -59,6 +59,7 @@ func injectTemplateToSpec(spec *testworkflowsv1.TestWorkflowSpec, template testw spec.Pod = MergePodConfig(template.Spec.Pod, spec.Pod) spec.Job = MergeJobConfig(template.Spec.Job, spec.Job) spec.Events = append(template.Spec.Events, spec.Events...) + spec.Execution = MergeExecution(template.Spec.Execution, spec.Execution) // Apply basic configuration spec.Content = MergeContent(template.Spec.Content, spec.Content) diff --git a/pkg/testworkflows/testworkflowresolver/merge.go b/pkg/testworkflows/testworkflowresolver/merge.go index a13dc33828b..5efa64c7a37 100644 --- a/pkg/testworkflows/testworkflowresolver/merge.go +++ b/pkg/testworkflows/testworkflowresolver/merge.go @@ -376,3 +376,21 @@ func ConvertIndependentStepToStep(step testworkflowsv1.IndependentStep) (res tes res.Steps = common.MapSlice(step.Steps, ConvertIndependentStepToStep) return res } + +func MergeExecution(dst, include *testworkflowsv1.TestWorkflowTagSchema) *testworkflowsv1.TestWorkflowTagSchema { + if dst == nil { + return include + } else if include == nil { + return dst + } + + if include.Tags != nil { + if dst.Tags == nil { + dst.Tags = make(map[string]string) + } + + maps.Copy(dst.Tags, include.Tags) + } + + return dst +}