From c5c8a8153d1fd71a75fbf1612c262f7aac3333fb Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Boll Date: Wed, 18 Dec 2024 14:12:40 +0100 Subject: [PATCH] Fix output chaining, make it possible to use output over RG border --- tooling/templatize/internal/end2end/e2e.go | 15 +++- .../templatize/internal/end2end/e2e_test.go | 71 ++++++++++++++++--- tooling/templatize/pkg/pipeline/run.go | 12 ++-- tooling/templatize/pkg/pipeline/run_test.go | 6 +- 4 files changed, 83 insertions(+), 21 deletions(-) diff --git a/tooling/templatize/internal/end2end/e2e.go b/tooling/templatize/internal/end2end/e2e.go index f48431fc5..ea2ad9bca 100644 --- a/tooling/templatize/internal/end2end/e2e.go +++ b/tooling/templatize/internal/end2end/e2e.go @@ -26,7 +26,7 @@ type E2E interface { SetConfig(updates config.Variables) UseRandomRG() func() error AddBicepTemplate(template, templateFileName, paramfile, paramfileName string) - AddStep(step pipeline.Step) + AddStep(step pipeline.Step, rg int) SetOSArgs() Persist() error } @@ -132,12 +132,21 @@ func (e *e2eImpl) SetOSArgs() { } } +func (e *e2eImpl) AddResourceGroup() { + numRgs := len(e.pipeline.ResourceGroups) + e.pipeline.ResourceGroups = append(e.pipeline.ResourceGroups, &pipeline.ResourceGroup{ + Name: fmt.Sprintf("{{ .rg }}-%d", numRgs+1), + Subscription: "{{ .subscription }}", + }, + ) +} + func (e *e2eImpl) SetAKSName(aksName string) { e.pipeline.ResourceGroups[0].AKSCluster = aksName } -func (e *e2eImpl) AddStep(step pipeline.Step) { - e.pipeline.ResourceGroups[0].Steps = append(e.pipeline.ResourceGroups[0].Steps, &step) +func (e *e2eImpl) AddStep(step pipeline.Step, rg int) { + e.pipeline.ResourceGroups[rg].Steps = append(e.pipeline.ResourceGroups[rg].Steps, &step) } func (e *e2eImpl) SetConfig(updates config.Variables) { diff --git a/tooling/templatize/internal/end2end/e2e_test.go b/tooling/templatize/internal/end2end/e2e_test.go index 63ccd231a..ffe9a46bf 100644 --- a/tooling/templatize/internal/end2end/e2e_test.go +++ b/tooling/templatize/internal/end2end/e2e_test.go @@ -45,7 +45,7 @@ func TestE2EMake(t *testing.T) { ConfigRef: "test_env", }, }, - }) + }, 0) e2eImpl.SetConfig(config.Variables{"defaults": config.Variables{"test_env": "test_env"}}) @@ -72,7 +72,7 @@ func TestE2EKubernetes(t *testing.T) { Name: "test", Action: "Shell", Command: "kubectl get namespaces", - }) + }, 0) e2eImpl.SetAKSName("aro-hcp-aks") e2eImpl.SetConfig(config.Variables{"defaults": config.Variables{"rg": "hcp-underlay-dev-svc"}}) @@ -93,7 +93,7 @@ func TestE2EArmDeploy(t *testing.T) { Action: "ARM", Template: "test.bicep", Parameters: "test.bicepparm", - }) + }, 0) cleanup := e2eImpl.UseRandomRG() defer func() { @@ -144,7 +144,7 @@ func TestE2EShell(t *testing.T) { Name: "readInput", Action: "Shell", Command: "/bin/echo ${PWD} > env.txt", - }) + }, 0) persistAndRun(t, &e2eImpl) @@ -166,7 +166,7 @@ func TestE2EArmDeployWithOutput(t *testing.T) { Action: "ARM", Template: "test.bicep", Parameters: "test.bicepparm", - }) + }, 0) e2eImpl.AddStep(pipeline.Step{ Name: "readInput", @@ -181,7 +181,7 @@ func TestE2EArmDeployWithOutput(t *testing.T) { }, }, }, - }) + }, 0) cleanup := e2eImpl.UseRandomRG() defer func() { @@ -217,7 +217,7 @@ func TestE2EArmDeployWithOutputToArm(t *testing.T) { Action: "ARM", Template: "testa.bicep", Parameters: "testa.bicepparm", - }) + }, 0) e2eImpl.AddStep(pipeline.Step{ Name: "parameterB", @@ -233,7 +233,7 @@ func TestE2EArmDeployWithOutputToArm(t *testing.T) { }, }, }, - }) + }, 0) e2eImpl.AddStep(pipeline.Step{ Name: "readInput", @@ -248,7 +248,7 @@ func TestE2EArmDeployWithOutputToArm(t *testing.T) { }, }, }, - }) + }, 0) e2eImpl.AddBicepTemplate(` param parameterA string @@ -281,3 +281,56 @@ param parameterB = '{{ .parameterB }}' assert.NilError(t, err) assert.Equal(t, string(io), "Hello Bicep\n") } + +func TestE2EArmDeployWithOutputRGOverlap(t *testing.T) { + if !shouldRunE2E() { + t.Skip("Skipping end-to-end tests") + } + + tmpDir := t.TempDir() + + e2eImpl := newE2E(tmpDir) + e2eImpl.AddStep(pipeline.Step{ + Name: "parameterA", + Action: "ARM", + Template: "testa.bicep", + Parameters: "testa.bicepparm", + }, 0) + + e2eImpl.AddResourceGroup() + + e2eImpl.AddStep(pipeline.Step{ + Name: "readInput", + Action: "Shell", + Command: "echo ${end} > env.txt", + Variables: []pipeline.Variable{ + { + Name: "end", + Input: &pipeline.Input{ + Name: "parameterA", + Step: "parameterA", + }, + }, + }, + }, 1) + + e2eImpl.AddBicepTemplate(` +param parameterA string +output parameterA string = parameterA`, + "testa.bicep", + ` +using 'testa.bicep' +param parameterA = 'Hello Bicep'`, + "testa.bicepparm") + + cleanup := e2eImpl.UseRandomRG() + defer func() { + err := cleanup() + assert.NilError(t, err) + }() + persistAndRun(t, &e2eImpl) + + io, err := os.ReadFile(tmpDir + "/env.txt") + assert.NilError(t, err) + assert.Equal(t, string(io), "Hello Bicep\n") +} diff --git a/tooling/templatize/pkg/pipeline/run.go b/tooling/templatize/pkg/pipeline/run.go index 4373df0fe..4cb6a239f 100644 --- a/tooling/templatize/pkg/pipeline/run.go +++ b/tooling/templatize/pkg/pipeline/run.go @@ -80,6 +80,8 @@ func (o armOutput) GetValue(key string) (*outPutValue, error) { func (p *Pipeline) Run(ctx context.Context, options *PipelineRunOptions) error { logger := logr.FromContextOrDiscard(ctx) + outPuts := make(map[string]output) + // set working directory to the pipeline file directory for the // duration of the execution so that all commands and file references // within the pipeline file are resolved relative to the pipeline file @@ -114,7 +116,7 @@ func (p *Pipeline) Run(ctx context.Context, options *PipelineRunOptions) error { resourceGroup: rg.Name, aksClusterName: rg.AKSCluster, } - err = rg.run(ctx, options, &executionTarget) + err = rg.run(ctx, options, &executionTarget, outPuts) if err != nil { return err } @@ -122,11 +124,9 @@ func (p *Pipeline) Run(ctx context.Context, options *PipelineRunOptions) error { return nil } -func (rg *ResourceGroup) run(ctx context.Context, options *PipelineRunOptions, executionTarget ExecutionTarget) error { +func (rg *ResourceGroup) run(ctx context.Context, options *PipelineRunOptions, executionTarget ExecutionTarget, outputs map[string]output) error { logger := logr.FromContextOrDiscard(ctx) - outPuts := make(map[string]output) - kubeconfigFile, err := executionTarget.KubeConfig(ctx) if kubeconfigFile != "" { defer func() { @@ -152,13 +152,13 @@ func (rg *ResourceGroup) run(ctx context.Context, options *PipelineRunOptions, e ), kubeconfigFile, executionTarget, options, - outPuts, + outputs, ) if err != nil { return err } if output != nil { - outPuts[step.Name] = output + outputs[step.Name] = output } } return nil diff --git a/tooling/templatize/pkg/pipeline/run_test.go b/tooling/templatize/pkg/pipeline/run_test.go index fe6ea1f1c..9874cb71e 100644 --- a/tooling/templatize/pkg/pipeline/run_test.go +++ b/tooling/templatize/pkg/pipeline/run_test.go @@ -49,7 +49,7 @@ func TestResourceGroupRun(t *testing.T) { }, }, } - err := rg.run(context.Background(), &PipelineRunOptions{}, &executionTargetImpl{}) + err := rg.run(context.Background(), &PipelineRunOptions{}, &executionTargetImpl{}, make(map[string]output)) assert.NilError(t, err) assert.Equal(t, foundOutput, "hello\n") } @@ -84,7 +84,7 @@ func TestResourceGroupError(t *testing.T) { }, }, } - err := rg.run(context.Background(), &PipelineRunOptions{}, &executionTargetImpl{}) + err := rg.run(context.Background(), &PipelineRunOptions{}, &executionTargetImpl{}, make(map[string]output)) assert.ErrorContains(t, err, "faaaaafffaa: command not found\n exit status 127") // Test processing ends after first error assert.Equal(t, len(tmpVals), 1) @@ -103,7 +103,7 @@ func (t *testExecutionTarget) GetRegion() string { return "test" } func TestResourceGroupRunRequireKubeconfig(t *testing.T) { rg := &ResourceGroup{Steps: []*Step{}} - err := rg.run(context.Background(), &PipelineRunOptions{}, &testExecutionTarget{}) + err := rg.run(context.Background(), &PipelineRunOptions{}, &testExecutionTarget{}, make(map[string]output)) assert.NilError(t, err) }