From a3fc5a92e44f4ae42e014d8add3b9118ccbc86f0 Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Thu, 19 Sep 2024 14:28:25 +0200 Subject: [PATCH] flux diff artifact: Add (and fix) unit tests. Signed-off-by: Florian Forster --- cmd/flux/diff_artifact_test.go | 71 ++++++++++++++++++- cmd/flux/main_test.go | 12 ++++ .../diff-artifact/deployment-diff.yaml | 2 +- .../testdata/diff-artifact/deployment.yaml | 2 +- 4 files changed, 83 insertions(+), 4 deletions(-) diff --git a/cmd/flux/diff_artifact_test.go b/cmd/flux/diff_artifact_test.go index 08e3c15e..fca6443c 100644 --- a/cmd/flux/diff_artifact_test.go +++ b/cmd/flux/diff_artifact_test.go @@ -22,6 +22,9 @@ package main import ( "context" "fmt" + "io" + "os" + "path/filepath" "testing" "time" @@ -65,6 +68,7 @@ func TestDiffArtifact(t *testing.T) { argsTpl string pushFile string diffFile string + diffName string assert assertFunc }{ { @@ -75,14 +79,50 @@ func TestDiffArtifact(t *testing.T) { diffFile: "./testdata/diff-artifact/deployment.yaml", assert: assertGoldenFile("testdata/diff-artifact/success.golden"), }, + { + name: "create unified diff output by default", + url: "oci://%s/podinfo:2.0.0", + argsTpl: "diff artifact %s --path=%s", + pushFile: "./testdata/diff-artifact/deployment.yaml", + diffFile: "./testdata/diff-artifact/deployment-diff.yaml", + diffName: "deployment.yaml", + assert: assert( + assertErrorIs(ErrDiffArtifactChanged), + assertRegexp(`(?m)^- cpu: 1000m$`), + assertRegexp(`(?m)^\+ cpu: 2000m$`), + ), + }, { name: "should fail if there is a diff", url: "oci://%s/podinfo:2.0.0", argsTpl: "diff artifact %s --path=%s", pushFile: "./testdata/diff-artifact/deployment.yaml", diffFile: "./testdata/diff-artifact/deployment-diff.yaml", - assert: assertErrorIs(ErrDiffArtifactChanged), + diffName: "only-local.yaml", + assert: assert( + assertErrorIs(ErrDiffArtifactChanged), + assertRegexp(`(?m)^Only in [^:]+: deployment.yaml$`), + assertRegexp(`(?m)^Only in [^:]+: only-local.yaml$`), + ), }, + { + name: "semantic diff using dyff", + url: "oci://%s/podinfo:2.0.0", + argsTpl: "diff artifact %s --path=%s --differ=dyff", + pushFile: "./testdata/diff-artifact/deployment.yaml", + diffFile: "./testdata/diff-artifact/deployment-diff.yaml", + diffName: "deployment.yaml", + assert: assert( + assertErrorIs(ErrDiffArtifactChanged), + assertRegexp(`(?m)^spec.template.spec.containers.podinfod.resources.limits.cpu$`), + assertRegexp(`(?m)^ ± value change$`), + assertRegexp(`(?m)^ - 1000m$`), + assertRegexp(`(?m)^ \+ 2000m$`), + ), + }, + // Attention: tests do not spawn a new process when executing commands. + // That means that the --differ flag remains set to "dyff" for + // subsequent tests. } ctx := ctrl.SetupSignalHandler() @@ -99,11 +139,38 @@ func TestDiffArtifact(t *testing.T) { t.Fatalf(fmt.Errorf("failed to push image: %w", err).Error()) } + diffFile := tt.diffFile + if tt.diffName != "" { + diffFile = makeTempFile(t, tt.diffFile, tt.diffName) + } + cmd := cmdTestCase{ - args: fmt.Sprintf(tt.argsTpl, tt.url, tt.diffFile), + args: fmt.Sprintf(tt.argsTpl, tt.url, diffFile), assert: tt.assert, } cmd.runTestCmd(t) }) } } + +func makeTempFile(t *testing.T, source, basename string) string { + path := filepath.Join(t.TempDir(), basename) + out, err := os.Create(path) + if err != nil { + t.Fatal(err) + } + defer out.Close() + + in, err := os.Open(source) + if err != nil { + t.Fatal(err) + } + defer in.Close() + + _, err = io.Copy(out, in) + if err != nil { + t.Fatal(err) + } + + return path +} diff --git a/cmd/flux/main_test.go b/cmd/flux/main_test.go index d25de059..87ad0a40 100644 --- a/cmd/flux/main_test.go +++ b/cmd/flux/main_test.go @@ -26,6 +26,7 @@ import ( "io" "os" "path/filepath" + "regexp" "strings" "sync/atomic" "testing" @@ -338,6 +339,17 @@ func assertGoldenTemplateFile(goldenFile string, templateValues map[string]strin }) } +func assertRegexp(expected string) assertFunc { + re := regexp.MustCompile(expected) + + return func(output string, _ error) error { + if !re.MatchString(output) { + return fmt.Errorf("Output does not match regular expression:\nOutput:\n%s\n\nRegular expression:\n%s", output, expected) + } + return nil + } +} + type TestClusterMode int const ( diff --git a/cmd/flux/testdata/diff-artifact/deployment-diff.yaml b/cmd/flux/testdata/diff-artifact/deployment-diff.yaml index 350d4c1b..3910da6a 100644 --- a/cmd/flux/testdata/diff-artifact/deployment-diff.yaml +++ b/cmd/flux/testdata/diff-artifact/deployment-diff.yaml @@ -4,7 +4,7 @@ metadata: labels: kustomize.toolkit.fluxcd.io/name: podinfo kustomize.toolkit.fluxcd.io/namespace: {{ .fluxns }} - name: podinfo-diff + name: podinfo namespace: default spec: minReadySeconds: 3 diff --git a/cmd/flux/testdata/diff-artifact/deployment.yaml b/cmd/flux/testdata/diff-artifact/deployment.yaml index 3910da6a..dc7584c5 100644 --- a/cmd/flux/testdata/diff-artifact/deployment.yaml +++ b/cmd/flux/testdata/diff-artifact/deployment.yaml @@ -71,7 +71,7 @@ spec: timeoutSeconds: 5 resources: limits: - cpu: 2000m + cpu: 1000m memory: 512Mi requests: cpu: 100m