diff --git a/.github/workflows/e2e-nightly.yaml b/.github/workflows/e2e-nightly.yaml new file mode 100644 index 0000000000..60245716b9 --- /dev/null +++ b/.github/workflows/e2e-nightly.yaml @@ -0,0 +1,91 @@ +name: E2E (nightly) + +on: + # schedule: + # Nightly at 03:00 UTC. + # - cron: "0 3 * * *" + workflow_dispatch: + +permissions: + contents: read + +jobs: + e2e: + runs-on: ubuntu-latest + # Test provisions kind cluster, cert-manager, Argo CD and Kargo, so the full run takes a while. + timeout-minutes: 180 + steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1 + with: + egress-policy: audit + + - name: Checkout code + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Install Go + uses: actions/setup-go@v5 + with: + # Use the e2e module's toolchain version. + go-version-file: hack/test/e2e/go.mod + cache-dependency-path: | + go.sum + hack/test/e2e/go.sum + + # The test shells out to helm, kind, kargo and argocd; install them all into + # hack/bin, which is added to PATH for the subsequent steps. + - name: Add hack/bin to PATH + run: echo "${GITHUB_WORKSPACE}/hack/bin" >> "${GITHUB_PATH}" + + - name: Install helm + run: make install-helm + + - name: Build kind + run: go build -o hack/bin/kind sigs.k8s.io/kind + + - name: Build kargo CLI + run: go build -o hack/bin/kargo ./cmd/cli + + - name: Install argocd CLI + run: | + curl -fsSL -o hack/bin/argocd \ + https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64 + chmod +x hack/bin/argocd + + - name: Verify tools + run: | + go version + helm version + kind version + kargo version --client || true + argocd version --client + + # nightly_config.yaml ships with an empty `context` section. Populate it from + # repository secrets so the git- and http-dependent suites can run. Each key + # is only written when its secret is set; suites whose context is missing + # skip or fail on their own. + - name: Configure e2e context + env: + E2E_KARGO_DEMO_GITOPS_REPO: ${{ secrets.E2E_KARGO_DEMO_GITOPS_REPO }} + E2E_GIT_PAT: ${{ secrets.E2E_GIT_PAT }} + ## TODO: We need to set up the endpoint to ebable that + # E2E_HTTP_ENDPOINT: ${{ secrets.E2E_HTTP_ENDPOINT }} + run: | + cfg=hack/test/e2e/envs/nightly_config.yaml + # Drop the existing (last) context section and re-add it from secrets. + sed -i '/^context:/,$d' "${cfg}" + { + echo "context:" + [ -n "${E2E_KARGO_DEMO_GITOPS_REPO}" ] && echo " kargo_demo_gitops_repo: ${E2E_KARGO_DEMO_GITOPS_REPO}" + [ -n "${E2E_GIT_PAT}" ] && echo " git_pat: ${E2E_GIT_PAT}" + [ -n "${E2E_HTTP_ENDPOINT}" ] && echo " http_endpoint: ${E2E_HTTP_ENDPOINT}" + } >> "${cfg}" + + - name: Build kargo image + run: | + make hack-build + + - name: Run e2e tests + working-directory: hack/test/e2e + run: | + go test -tags=e2e,shared ./suites/shared -timeout 120m -args -env-file=nightly_config.yaml diff --git a/hack/test/e2e/envs/kind_config.yaml b/hack/test/e2e/envs/kind_config.yaml index 2875163a6e..11570b4eb9 100644 --- a/hack/test/e2e/envs/kind_config.yaml +++ b/hack/test/e2e/envs/kind_config.yaml @@ -30,6 +30,11 @@ cert_manager: set: [] values_files: [] +## argo-rollouts are required for AnalysisTemplate in kargo +argo-rollouts: + namespace: argo-rollouts + timeout: 10m + argocd: release_name: argocd namespace: argocd diff --git a/hack/test/e2e/envs/nightly_config.yaml b/hack/test/e2e/envs/nightly_config.yaml new file mode 100644 index 0000000000..e66c69d8ae --- /dev/null +++ b/hack/test/e2e/envs/nightly_config.yaml @@ -0,0 +1,51 @@ +## Environment template used to configure nightly e2e runs. + +## It is based on kind_config.yaml and is going to use `kind` and `helm` to set up kargo and argocd instances. +description: "Nightly test wth kind cluster" + +cluster: + name: kargo-e2e + +## cert-manager is a prerequisite for Kargo's self-signed certificates. +cert_manager: + namespace: cert-manager + timeout: 10m + +argocd: + namespace: argocd + timeout: 10m + values_files: [ + ../../values.argocd.test.yaml + ] + +argo-rollouts: + namespace: argo-rollouts + timeout: 10m + +kargo: + namespace: kargo + ## Using a chart directly from the repo + chart: ../../../../../charts/kargo + ## Using an image built with make hack-build + image: docker.io/library/kargo:dev + timeout: 10m + values_files: [ + ../../values.test.yaml + ] + +kargo_cli: + ## Indicate that we need to run `kargo login` to login into a kargo instance in `kind` cluster + kargo_login: + ## Uste tmp directory to store kargo config + use_tmp_config_home: true + +argocd_cli: + ## Using system-local argocd config created by `argocd login` + config_file: ~/.config/argocd/config + ## Indicate that we need to run `argocd login` to login to an argocd instance in `kind` cluster + argocd_login: true + +context: + # kargo_demo_gitops_repo: + # git_pat: + # http_endpoint: \ No newline at end of file diff --git a/hack/test/e2e/framework/envfuncs/cluster.go b/hack/test/e2e/framework/envfuncs/cluster.go index dad01fa792..7c646f0a0d 100644 --- a/hack/test/e2e/framework/envfuncs/cluster.go +++ b/hack/test/e2e/framework/envfuncs/cluster.go @@ -25,6 +25,7 @@ const ClusterNameKey ContextKey = "cluster_name" // KargoHostKey holds a hostname used in KargoLogin. Populated by InstallKargo const KargoHostKey ContextKey = "kargo_host" + // KargoPasswordKey holds a password used in KargoLogin. Populated by InstallKargo const KargoPasswordKey ContextKey = "kargo_password" @@ -39,6 +40,7 @@ func ClusterSetupFuncs() []env.Func { CreateKindCluster, InstallCertManager, InstallArgoCD, + InstallArgoRollouts, InstallKargo, } } @@ -70,7 +72,7 @@ func CreateKindCluster(ctx context.Context, cfg *envconf.Config) (context.Contex } provider := kind.NewProvider() - + tempdir := ctx.Value(TmpDirKey) if tempdir == nil { return ctx, fmt.Errorf("Temp dir is not set up. Cannot create kubeconfig") @@ -178,7 +180,7 @@ func InstallArgoCD(ctx context.Context, cfg *envconf.Config) (context.Context, e } // Port from portForward above ctx = context.WithValue(ctx, ArgocdHostKey, "localhost:8080") - // Auth info. + // Auth info. // FIXME: the values require setValues to have configs.secret.argocdServerAdminPassword set // Currently set in values.argocd.test.yaml ctx = context.WithValue(ctx, ArgocdUsernameKey, "admin") @@ -239,17 +241,46 @@ func InstallKargo(ctx context.Context, cfg *envconf.Config) (context.Context, er return ctx, nil } +// InstallArgoRollouts installs the Argo Rollouts Helm chart. +// It no-ops when no managed cluster is present in the context. +func InstallArgoRollouts(ctx context.Context, cfg *envconf.Config) (context.Context, error) { + if _, ok := managedClusterName(ctx); !ok { + return ctx, nil + } + if _, err := GetEnvMap(ctx, []string{"argo-rollouts"}); err != nil { + fmt.Println("No `argo-rollouts` section in env; skipping argo rollouts installation") + return ctx, nil + } + chart := helmChart{ + releaseName: optionalString(ctx, []string{"argo-rollouts", "release_name"}, "argo-rollouts"), + chart: optionalString(ctx, []string{"argo-rollouts", "chart"}, "argo/argo-rollouts"), + namespace: optionalString(ctx, []string{"argo-rollouts", "namespace"}, "argo-rollouts"), + version: optionalString(ctx, []string{"argo-rollouts", "version"}, ""), + repoName: optionalString(ctx, []string{"argo-rollouts", "chart_repo_name"}, "argo"), + repoURL: optionalString(ctx, []string{"argo-rollouts", "chart_repo_url"}, "https://argoproj.github.io/argo-helm"), + timeout: optionalString(ctx, []string{"argo-rollouts", "timeout"}, "10m"), + valuesFiles: expandHomeAll(optionalStringSlice(ctx, []string{"argo-rollouts", "values_files"})), + setValues: optionalStringSlice(ctx, []string{"argo-rollouts", "set"}), + } + fmt.Println("Installing Argo Rollouts") + if err := chart.install(cfg.KubeconfigFile()); err != nil { + return ctx, fmt.Errorf("installing Argo Rollouts: %w", err) + } + + return ctx, nil +} + func portForward(kubeconfig, namespace, service string, outport, inport int) error { // Run port-forward in background. // This is a simplified approach when we just run a background shell. // There is no error handling here, it might fail silently. // FIXME: replace that with goroutine and error channels? // FIXME: implement forwarding to an non-predefined port - cmd := fmt.Sprintf("sh -c \"kubectl port-forward --kubeconfig %s --namespace %s %s %d:%d > /dev/null 2>&1 &\"", + cmd := fmt.Sprintf("sh -c \"kubectl port-forward --kubeconfig %s --namespace %s %s %d:%d > /dev/null 2>&1 &\"", kubeconfig, namespace, service, outport, inport) - fmt.Printf("Port forwarding %s to %d", service, outport) - + fmt.Printf("Port forwarding %s to %d\n", service, outport) + p := utils.RunCommand(cmd) if p.Err() != nil { outBytes, outErr := io.ReadAll(p.Out()) diff --git a/hack/test/e2e/framework/utils/features.go b/hack/test/e2e/framework/utils/features.go new file mode 100644 index 0000000000..6b8e8d562e --- /dev/null +++ b/hack/test/e2e/framework/utils/features.go @@ -0,0 +1,5 @@ +package utils + +import "sigs.k8s.io/e2e-framework/pkg/features" + +var TestFeatures []features.Feature diff --git a/hack/test/e2e/framework/utils/fixtures.go b/hack/test/e2e/framework/utils/fixtures.go deleted file mode 100644 index 0ef193f052..0000000000 --- a/hack/test/e2e/framework/utils/fixtures.go +++ /dev/null @@ -1,102 +0,0 @@ -package utils - -import ( - "context" - "os" - "testing" - - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/e2e-framework/klient/decoder" - "sigs.k8s.io/e2e-framework/klient/k8s/resources" - "sigs.k8s.io/e2e-framework/pkg/envconf" - "sigs.k8s.io/e2e-framework/pkg/features" - - "github.com/akuity/kargo/hack/test/e2e/envfuncs" -) - -const NamespaceKey envfuncs.ContextKey = "namespace" - -func SetupFixturesInNamespace(namespace string) features.Func { - return func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { - return SetupFixtures(context.WithValue(ctx, NamespaceKey, namespace), t, cfg) - } -} - -func SetupFixtures(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { - testdata := os.DirFS("testdata") - pattern := "*" - namespace, ok := ctx.Value(NamespaceKey).(string) - t.Logf("namespace %v\n", namespace) - if !ok { - t.Logf("Using config namespace \n") - namespace = cfg.Namespace() - } - r, err := resources.New(cfg.Client().RESTConfig()) - if err != nil { - t.Fatal(err) - } - if err := decoder.DecodeEachFile(ctx, testdata, pattern, - decoder.CreateHandler(r), // try to CREATE objects after decoding - decoder.MutateNamespace(namespace), // inject a namespace into decoded objects, before calling CreateHandler - ); err != nil { - t.Fatal(err) - } - return ctx -} - -func TeardownFixturesInNamespace(namespace string) features.Func { - return func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { - return TeardownFixtures(context.WithValue(ctx, NamespaceKey, namespace), t, cfg) - } -} - -func TeardownFixtures(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { - testdata := os.DirFS("testdata") - pattern := "*" - namespace, ok := ctx.Value(NamespaceKey).(string) - t.Logf("namespace %v\n", namespace) - if !ok { - t.Logf("Using config namespace \n") - namespace = cfg.Namespace() - } - r, err := resources.New(cfg.Client().RESTConfig()) - if err != nil { - t.Fatal(err) - } - if err := decoder.DecodeEachFile(ctx, testdata, pattern, - decoder.DeleteHandler(r), // try to DELETE objects after decoding - decoder.MutateNamespace(namespace), // inject a namespace into decoded objects, before calling CreateHandler - ); err != nil { - t.Fatal(err) - } - return ctx -} - -func CreateNamespace(namespace string) features.Func { - return func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { - client := cfg.Client() - ns := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{Name: namespace}, - } - t.Logf("CREATE namespace %v\n", ns) - if err := client.Resources().Create(ctx, ns); err != nil { - t.Fatal(err) - } - return ctx - } -} - -func DeleteNamespace(namespace string) features.Func { - return func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { - client := cfg.Client() - ns := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{Name: namespace}, - } - t.Logf("DELETE namespace %v\n", ns) - if err := client.Resources().Delete(ctx, ns); err != nil { - t.Fatal(err) - } - return ctx - } -} diff --git a/hack/test/e2e/framework/utils/kargo_fixtures.go b/hack/test/e2e/framework/utils/kargo_fixtures.go index 01a735b1f8..3ef2f1d6cc 100644 --- a/hack/test/e2e/framework/utils/kargo_fixtures.go +++ b/hack/test/e2e/framework/utils/kargo_fixtures.go @@ -4,7 +4,7 @@ import ( "context" "errors" "fmt" - "os" + "io/fs" "path/filepath" "slices" "strings" @@ -26,6 +26,8 @@ import ( const groupKargo = "kargo" const KargoCLIKey envfuncs.ContextKey = "kargo_cli" const KargoCLIWatchKey envfuncs.ContextKey = "kargo_watch" +const TestDataPath = "testdata" +const TestDataKey envfuncs.ContextKey = "test_data" func SetupKargoClients(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { ctx = SetupKargoApiClient(ctx, t, cfg) @@ -113,15 +115,26 @@ func TeardownKargoFixtures(ctx context.Context, t *testing.T, cfg *envconf.Confi return TeardownKargoFixturesWithOptions(ctx, t, cfg) } +func TestData(testData fs.FS) features.Func { + return func(ctx context.Context, _ *testing.T, _ *envconf.Config) context.Context { + return context.WithValue(ctx, TestDataKey, testData) + } +} + func scanFixtures( ctx context.Context, group string, sortFun func([]string) []string, handlerFun decoder.HandlerFunc, - options ...decoder.DecodeOption) error { + options ...decoder.DecodeOption, +) error { + testData, ok := ctx.Value(TestDataKey).(fs.FS) + if !ok { + return fmt.Errorf("unable to get testdata from context") + } - fixturesDir := filepath.Join("testdata", group) - files, err := filepath.Glob(filepath.Join(fixturesDir, "*.yaml")) + fixturesDir := filepath.Join(TestDataPath, group) + files, err := fs.Glob(testData, filepath.Join(fixturesDir, "*.yaml")) if err != nil { return err } @@ -129,7 +142,7 @@ func scanFixtures( files = sortFun(files) for _, file := range files { - err := scanFile(ctx, file, handlerFun, options...) + err := scanFile(ctx, testData, file, handlerFun, options...) if err != nil { return err } @@ -140,11 +153,12 @@ func scanFixtures( func scanFile( ctx context.Context, + testData fs.FS, fileName string, handlerFun decoder.HandlerFunc, options ...decoder.DecodeOption, ) error { - f, err := os.Open(fileName) + f, err := testData.Open(fileName) if err != nil { return err } @@ -153,7 +167,7 @@ func scanFile( if err != nil { return err } - return f.Close() + return nil } func sortDesc(sorted []string) []string { @@ -179,8 +193,9 @@ func KargoCreateHandler() decoder.HandlerFunc { return fmt.Errorf("kargo_cli is required in context") } + fmt.Printf("Create kargo resource %v : %v\n", obj.GetObjectKind().GroupVersionKind().Kind, obj.GetName()) + manifest, err := yaml.Marshal(obj) - fmt.Printf("Creating resource: %v\n", obj.GetObjectKind()) if err != nil { return fmt.Errorf("error encoding kargo resource manifest: %w", err) } diff --git a/hack/test/e2e/framework/utils/kargo_functions.go b/hack/test/e2e/framework/utils/kargo_functions.go index bd862bcd8d..f49684253b 100644 --- a/hack/test/e2e/framework/utils/kargo_functions.go +++ b/hack/test/e2e/framework/utils/kargo_functions.go @@ -3,7 +3,6 @@ package utils import ( "errors" - "fmt" "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/e2e-framework/klient/decoder" @@ -13,7 +12,6 @@ import ( func UpdatePromotionTasksVar(name, key, val string) decoder.DecodeOption { return MutateAsUnstructuredOptionFor("PromotionTask", name, func(unstr runtime.Unstructured) error { data := unstr.UnstructuredContent() - fmt.Printf("Parsed data %v\n", data) for _, tplVar := range data["spec"].(map[string]any)["vars"].([]any) { tplVarMap := tplVar.(map[string]any) if tplVarMap["name"] == key { @@ -21,8 +19,6 @@ func UpdatePromotionTasksVar(name, key, val string) decoder.DecodeOption { } } - fmt.Printf("Updated data %v\n", data) - unstr.SetUnstructuredContent(data) return nil }) @@ -31,7 +27,6 @@ func UpdatePromotionTasksVar(name, key, val string) decoder.DecodeOption { func UpdateWarehouseGitRepoURL(name, repoURL string) decoder.DecodeOption { return MutateAsUnstructuredOptionFor("Warehouse", name, func(unstr runtime.Unstructured) error { data := unstr.UnstructuredContent() - fmt.Printf("Parsed data %v\n", data) for _, sub := range data["spec"].(map[string]any)["subscriptions"].([]any) { subMap := sub.(map[string]any) @@ -41,8 +36,6 @@ func UpdateWarehouseGitRepoURL(name, repoURL string) decoder.DecodeOption { } } - fmt.Printf("Updated data %v\n", data) - unstr.SetUnstructuredContent(data) return nil }) diff --git a/hack/test/e2e/framework/utils/kargo_promotions.go b/hack/test/e2e/framework/utils/kargo_promotions.go index f2c2d82a87..b540012a3b 100644 --- a/hack/test/e2e/framework/utils/kargo_promotions.go +++ b/hack/test/e2e/framework/utils/kargo_promotions.go @@ -4,7 +4,6 @@ package utils import ( "context" "errors" - "fmt" "net/http" "strings" "testing" @@ -428,37 +427,5 @@ func GetFreight(ctx context.Context, project, freightID string) (*generated.Frei if err != nil { return nil, err } - fmt.Printf("FREIGHT: %v", freightOK) return freightOK, nil } - -// func getAnyFreight(kargoClient generated.APIClient, project, origin string) (*kargoapi.Freight, error) { - -// params := core.NewQueryFreightsRestParams().WithProject(project).WithOrigins([]string{origin}) - -// freightRes, err := kargoClient.CoreAPI.QueryFreightsRest(params, nil) -// if err != nil { -// return nil, fmt.Errorf("Error querying freight %v", err) -// } - -// // FIXME: change that once we make freight response typed -// var freightJSON []byte -// if freightJSON, err = json.Marshal(freightRes); err != nil { -// return nil, fmt.Errorf("marshal freight: %w", err) -// } -// // The response is {"groups": {"": {"items": [...]}}} -// type freightList struct { -// Items []*kargoapi.Freight `json:"items"` -// } -// var result struct { -// Groups map[string]*freightList `json:"groups"` -// } -// if err = json.Unmarshal(freightJSON, &result); err != nil { -// return nil, fmt.Errorf("unmarshal freight: %v", err) -// } -// freights := result.Groups[""].Items -// if len(freights) < 1 { -// return nil, fmt.Errorf("no freights found") -// } -// return freights[0], nil -// } diff --git a/hack/test/e2e/suites/argocd_helm_chart/argocd_helm_chart_test.go b/hack/test/e2e/suites/argocd_helm_chart/argocd_helm_chart_test.go index 6c56ff4573..ce1cbee26d 100644 --- a/hack/test/e2e/suites/argocd_helm_chart/argocd_helm_chart_test.go +++ b/hack/test/e2e/suites/argocd_helm_chart/argocd_helm_chart_test.go @@ -1,24 +1,14 @@ //go:build e2e //nolint:forcetypeassert -package argocd_helm_chart_test +package argocd_helm_chart // This test implements the Argo CD driven, Helm chart-only example from // https://github.com/akuity/kargo-examples (01-argocd-driven/02-helm-driven/01-chart-only). -// Stage-specific Argo CD Applications point at a specific version of the nginx -// chart in the Bitnami chart repository, and Kargo advances new chart versions -// from stage to stage. AnalysisTemplate verification is stripped (see -// testdata/review/verification.yaml). +// Stage-specific Argo CD Applications point at a specific version of the chart, and Kargo advances new chart versions +// from stage to stage. import ( - "context" "testing" - "time" - - "sigs.k8s.io/e2e-framework/pkg/envconf" - "sigs.k8s.io/e2e-framework/pkg/features" - - kargoapi "github.com/akuity/kargo/api/v1alpha1" - "github.com/akuity/kargo/hack/test/e2e/envfuncs" "github.com/akuity/kargo/hack/test/e2e/framework/utils" ) @@ -29,60 +19,7 @@ func TestMain(m *testing.M) { } func TestArgocdHelmChart(t *testing.T) { - feature := features.New("argocd-helm-chart") - - project := "kargo-argocd-helm-chart" - origin := "kargo-demo" - - feature.Setup(utils.SetupArgocdClient) - feature.Setup(utils.SetupArgoCDFixtures) - // feature.Teardown(utils.TeardownArgoCDFixtures) - - feature.Setup(utils.SetupKargoClients) - - // Setup and teardown fixtures from testdata folder. - // This example subscribes to a public Helm chart repository, so no repo - // URL substitution is required. - feature.Setup(utils.RequireKargoCli) - feature.Setup(utils.SetupKargoFixtures) - feature.Teardown(utils.TeardownKargoFixtures) - - feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - t.Logf("Require freight \n") - - anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - t.Logf("Freight: %v", anyFreightID) - return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) - }) - - for _, stage := range []string{"test", "uat", "prod"} { - feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - - t.Logf("Promoting %v to %v \n", stage, freightID) - - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - - if _, err := utils.PromoteAndWaitForPhase( - ctx, t, - project, stage, freightID, - kargoapi.PromotionPhaseSucceeded, - 10*time.Minute, - ); err != nil { - t.Fatal(err) - } - - _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) - - return ctx - }) - } - - utils.TestEnv.Test(t, feature.Feature()) + // Actual test code lives in test_code.go + // This is a trick to allow shared run between multiple packages + utils.TestEnv.Test(t, feature()) } diff --git a/hack/test/e2e/suites/argocd_helm_chart/feature.go b/hack/test/e2e/suites/argocd_helm_chart/feature.go new file mode 100644 index 0000000000..eec48cc309 --- /dev/null +++ b/hack/test/e2e/suites/argocd_helm_chart/feature.go @@ -0,0 +1,87 @@ +//nolint:forcetypeassert +package argocd_helm_chart + +import ( + "context" + "embed" + "testing" + "time" + + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/hack/test/e2e/envfuncs" + "github.com/akuity/kargo/hack/test/e2e/framework/utils" +) + +func init() { + utils.TestFeatures = append(utils.TestFeatures, feature()) +} + +var ( + //go:embed testdata/* + TestData embed.FS +) + +func feature() features.Feature { + feature := features.New("argocd-helm-chart") + + project := "kargo-argocd-helm-chart" + origin := "kargo-demo" + + // This setup step is necessary to use this feature as a part of shared package test + // It sets the path to look up the fixtures files. + feature.Setup(utils.TestData(TestData)) + feature.Setup(utils.SetupArgocdClient) + feature.Setup(utils.SetupArgoCDFixtures) + feature.Teardown(utils.TeardownArgoCDFixtures) + + feature.Setup(utils.SetupKargoClients) + + // Setup and teardown fixtures from testdata folder. + // This example subscribes to a public Helm chart repository, so no repo + // URL substitution is required. + feature.Setup(utils.RequireKargoCli) + feature.Setup(utils.SetupKargoFixtures) + feature.Teardown(utils.TeardownKargoFixtures) + + feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + t.Logf("Require freight \n") + + anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + t.Logf("Freight: %v", anyFreightID) + return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) + }) + + for _, stage := range []string{"test", "uat", "prod"} { + feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + + t.Logf("Promoting %v to %v \n", stage, freightID) + + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + + if _, err := utils.PromoteAndWaitForPhase( + ctx, t, + project, stage, freightID, + kargoapi.PromotionPhaseSucceeded, + 10*time.Minute, + ); err != nil { + t.Fatal(err) + } + + _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) + + return ctx + }) + } + + return feature.Feature() +} diff --git a/hack/test/e2e/suites/argocd_helm_chart/testdata/argocd/argocd.yaml b/hack/test/e2e/suites/argocd_helm_chart/testdata/argocd/argocd.yaml index 2081bff45b..1a90daf03c 100644 --- a/hack/test/e2e/suites/argocd_helm_chart/testdata/argocd/argocd.yaml +++ b/hack/test/e2e/suites/argocd_helm_chart/testdata/argocd/argocd.yaml @@ -18,14 +18,10 @@ spec: spec: project: default source: - repoURL: https://charts.bitnami.com/bitnami - chart: nginx + repoURL: https://grafana-community.github.io/helm-charts + chart: grafana # Kargo will update targetRevision to move new charts into each stage targetRevision: placeholder - helm: - parameters: - - name: service.type - value: ClusterIP destination: server: https://kubernetes.default.svc namespace: kargo-argocd-helm-chart-{{stage}} diff --git a/hack/test/e2e/suites/argocd_helm_chart/testdata/kargo/kargo.yaml b/hack/test/e2e/suites/argocd_helm_chart/testdata/kargo/kargo.yaml index 9f2509f162..5bb8a60279 100644 --- a/hack/test/e2e/suites/argocd_helm_chart/testdata/kargo/kargo.yaml +++ b/hack/test/e2e/suites/argocd_helm_chart/testdata/kargo/kargo.yaml @@ -11,9 +11,9 @@ metadata: spec: subscriptions: - chart: - repoURL: https://charts.bitnami.com/bitnami - name: nginx # Watch for new versions of this chart - semverConstraint: ^14.1.0 + repoURL: https://grafana-community.github.io/helm-charts + name: grafana + semverConstraint: ^12.0.0 --- apiVersion: kargo.akuity.io/v1alpha1 kind: PromotionTask @@ -23,7 +23,7 @@ metadata: spec: vars: - name: chartRepo - value: https://charts.bitnami.com/bitnami + value: https://grafana-community.github.io/helm-charts steps: - uses: argocd-update config: @@ -31,8 +31,8 @@ spec: - name: ${{ ctx.project }}-${{ ctx.stage }} sources: - repoURL: ${{ vars.chartRepo }} - chart: nginx - desiredRevision: ${{ chartFrom(vars.chartRepo, "nginx").Version }} + chart: grafana + desiredRevision: ${{ chartFrom(vars.chartRepo, "grafana").Version }} updateTargetRevision: true --- apiVersion: kargo.akuity.io/v1alpha1 diff --git a/hack/test/e2e/suites/argocd_helm_chart_n_image/argocd_helm_chart_n_image_test.go b/hack/test/e2e/suites/argocd_helm_chart_n_image/argocd_helm_chart_n_image_test.go index 1f84d29a1f..2aa6f04626 100644 --- a/hack/test/e2e/suites/argocd_helm_chart_n_image/argocd_helm_chart_n_image_test.go +++ b/hack/test/e2e/suites/argocd_helm_chart_n_image/argocd_helm_chart_n_image_test.go @@ -1,25 +1,17 @@ //go:build e2e //nolint:forcetypeassert -package argocd_helm_chart_n_image_test +package argocd_helm_chart_n_image // This test implements the Argo CD driven, Helm chart-and-image example from // https://github.com/akuity/kargo-examples (01-argocd-driven/02-helm-driven/03-chart-n-image). -// Stage-specific Argo CD Applications point at a specific version of the nginx -// chart in the Bitnami chart repository and set the nginx image tag from a +// Stage-specific Argo CD Applications point at a specific version of the +// chart in the chart repository and set the image tag from a // public image repository, and Kargo advances new chart versions and image -// tags from stage to stage. AnalysisTemplate verification is stripped (see -// testdata/review/verification.yaml). +// tags from stage to stage. import ( - "context" "testing" - "time" - "sigs.k8s.io/e2e-framework/pkg/envconf" - "sigs.k8s.io/e2e-framework/pkg/features" - - kargoapi "github.com/akuity/kargo/api/v1alpha1" - "github.com/akuity/kargo/hack/test/e2e/envfuncs" "github.com/akuity/kargo/hack/test/e2e/framework/utils" ) @@ -30,60 +22,5 @@ func TestMain(m *testing.M) { } func TestArgocdHelmChartNImage(t *testing.T) { - feature := features.New("argocd-helm-chart-n-image") - - project := "kargo-argocd-helm-chart-image" - origin := "kargo-demo" - - feature.Setup(utils.SetupArgocdClient) - feature.Setup(utils.SetupArgoCDFixtures) - feature.Teardown(utils.TeardownArgoCDFixtures) - - feature.Setup(utils.SetupKargoClients) - - // Setup and teardown fixtures from testdata folder. - // This example subscribes to a public Helm chart repository, so no repo - // URL substitution is required. - feature.Setup(utils.RequireKargoCli) - feature.Setup(utils.SetupKargoFixtures) - feature.Teardown(utils.TeardownKargoFixtures) - - feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - t.Logf("Require freight \n") - - anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - t.Logf("Freight: %v", anyFreightID) - return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) - }) - - for _, stage := range []string{"test", "uat", "prod"} { - feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - - t.Logf("Promoting %v to %v \n", stage, freightID) - - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - - if _, err := utils.PromoteAndWaitForPhase( - ctx, t, - project, stage, freightID, - kargoapi.PromotionPhaseSucceeded, - 10*time.Minute, - ); err != nil { - t.Fatal(err) - } - - _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) - - return ctx - }) - } - - utils.TestEnv.Test(t, feature.Feature()) + utils.TestEnv.Test(t, feature()) } diff --git a/hack/test/e2e/suites/argocd_helm_chart_n_image/feature.go b/hack/test/e2e/suites/argocd_helm_chart_n_image/feature.go new file mode 100644 index 0000000000..668696e16b --- /dev/null +++ b/hack/test/e2e/suites/argocd_helm_chart_n_image/feature.go @@ -0,0 +1,88 @@ +//nolint:forcetypeassert +package argocd_helm_chart_n_image + +import ( + "context" + "embed" + "testing" + "time" + + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/hack/test/e2e/envfuncs" + "github.com/akuity/kargo/hack/test/e2e/framework/utils" +) + +func init() { + utils.TestFeatures = append(utils.TestFeatures, feature()) +} + +var ( + //go:embed testdata/* + TestData embed.FS +) + +func feature() features.Feature { + feature := features.New("argocd-helm-chart-n-image") + + // This setup step is necessary to use this feature as a part of shared package test + // It sets the path to look up the fixtures files. + feature.Setup(utils.TestData(TestData)) + + project := "kargo-argocd-helm-chart-image" + origin := "kargo-demo" + + feature.Setup(utils.SetupArgocdClient) + feature.Setup(utils.SetupArgoCDFixtures) + feature.Teardown(utils.TeardownArgoCDFixtures) + + feature.Setup(utils.SetupKargoClients) + + // Setup and teardown fixtures from testdata folder. + // This example subscribes to a public Helm chart repository, so no repo + // URL substitution is required. + feature.Setup(utils.RequireKargoCli) + feature.Setup(utils.SetupKargoFixtures) + feature.Teardown(utils.TeardownKargoFixtures) + + feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + t.Logf("Require freight \n") + + anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + t.Logf("Freight: %v", anyFreightID) + return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) + }) + + for _, stage := range []string{"test", "uat", "prod"} { + feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + + t.Logf("Promoting %v to %v \n", stage, freightID) + + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + + if _, err := utils.PromoteAndWaitForPhase( + ctx, t, + project, stage, freightID, + kargoapi.PromotionPhaseSucceeded, + 10*time.Minute, + ); err != nil { + t.Fatal(err) + } + + _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) + + return ctx + }) + } + + return feature.Feature() +} diff --git a/hack/test/e2e/suites/argocd_helm_chart_n_image/testdata/argocd/argocd.yaml b/hack/test/e2e/suites/argocd_helm_chart_n_image/testdata/argocd/argocd.yaml index 9049c63454..add66846ff 100644 --- a/hack/test/e2e/suites/argocd_helm_chart_n_image/testdata/argocd/argocd.yaml +++ b/hack/test/e2e/suites/argocd_helm_chart_n_image/testdata/argocd/argocd.yaml @@ -18,8 +18,8 @@ spec: spec: project: default source: - repoURL: https://charts.bitnami.com/bitnami - chart: nginx + repoURL: https://grafana-community.github.io/helm-charts + chart: grafana # Kargo will update targetRevision to move new charts into each stage targetRevision: placeholder helm: @@ -27,8 +27,6 @@ spec: # Kargo will update this value to move new images into each stage - name: image.tag value: placeholder - - name: service.type - value: ClusterIP destination: server: https://kubernetes.default.svc namespace: kargo-argocd-helm-chart-image-{{stage}} diff --git a/hack/test/e2e/suites/argocd_helm_chart_n_image/testdata/kargo/kargo.yaml b/hack/test/e2e/suites/argocd_helm_chart_n_image/testdata/kargo/kargo.yaml index 9c9a7c40aa..eaafaf2955 100644 --- a/hack/test/e2e/suites/argocd_helm_chart_n_image/testdata/kargo/kargo.yaml +++ b/hack/test/e2e/suites/argocd_helm_chart_n_image/testdata/kargo/kargo.yaml @@ -11,12 +11,12 @@ metadata: spec: subscriptions: - chart: - repoURL: https://charts.bitnami.com/bitnami - name: nginx # Watch for new versions of this chart - semverConstraint: ^14.1.0 + repoURL: https://grafana-community.github.io/helm-charts + name: grafana # Watch for new versions of this chart + semverConstraint: ^12.0.0 - image: - repoURL: public.ecr.aws/nginx/nginx # Watch for new versions of this image - semverConstraint: ^1.24.0 + repoURL: docker.io/grafana/grafana # Watch for new versions of this image + semverConstraint: ^13.0 --- apiVersion: kargo.akuity.io/v1alpha1 kind: PromotionTask @@ -26,9 +26,9 @@ metadata: spec: vars: - name: chartRepo - value: https://charts.bitnami.com/bitnami + value: https://grafana-community.github.io/helm-charts - name: imageRepo - value: public.ecr.aws/nginx/nginx + value: docker.io/grafana/grafana steps: - uses: argocd-update config: @@ -36,8 +36,8 @@ spec: - name: ${{ ctx.project }}-${{ ctx.stage }} sources: - repoURL: ${{ vars.chartRepo }} - chart: nginx - desiredRevision: ${{ chartFrom(vars.chartRepo, "nginx").Version }} + chart: grafana + desiredRevision: ${{ chartFrom(vars.chartRepo, "grafana").Version }} updateTargetRevision: true helm: images: diff --git a/hack/test/e2e/suites/argocd_helm_commit_n_image/argocd_helm_commit_n_image_test.go b/hack/test/e2e/suites/argocd_helm_commit_n_image/argocd_helm_commit_n_image_test.go index 92ca82f43a..cb8f1d2291 100644 --- a/hack/test/e2e/suites/argocd_helm_commit_n_image/argocd_helm_commit_n_image_test.go +++ b/hack/test/e2e/suites/argocd_helm_commit_n_image/argocd_helm_commit_n_image_test.go @@ -1,20 +1,13 @@ //go:build e2e //nolint:forcetypeassert -package argocd_helm_commit_n_image_test +package argocd_helm_commit_n_image // This test implements an example of promoting argocd applications similar to https://github.com/akuity/kargo-examples // The difference is that this example does not have an AnalysisTemplate verification. import ( - "context" "testing" - "time" - "sigs.k8s.io/e2e-framework/pkg/envconf" - "sigs.k8s.io/e2e-framework/pkg/features" - - kargoapi "github.com/akuity/kargo/api/v1alpha1" - "github.com/akuity/kargo/hack/test/e2e/envfuncs" "github.com/akuity/kargo/hack/test/e2e/framework/utils" ) @@ -25,71 +18,5 @@ func TestMain(m *testing.M) { } func TestArgocdHelmCommitNImage(t *testing.T) { - feature := features.New("argocd-helm-commit-n-image") - - project := "kargo-argocd-helm-commit-image" - origin := "kargo-demo" - - feature.Setup(utils.SetupArgocdClient) - // Point the Argo CD ApplicationSet's source at the fork of the demo GitOps - // repository, mirroring the substitution applied to the Kargo fixtures. - feature.Setup(utils.SetupArgoCDFixturesWithRepoURL(project)) - feature.Teardown(utils.TeardownArgoCDFixtures) - - feature.Setup(utils.SetupKargoClients) - - // Setup and teardown fixtures from testdata folder - feature.Setup(utils.RequireKargoCli) - feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { - kargoDemoRepoVal, err := envfuncs.GetEnv(ctx, []string{"context", "kargo_demo_gitops_repo"}) - if err != nil { - t.Fatalf("cannot get kargo_demo_gitops_repo %v", err) - } - kargoDemoRepo := kargoDemoRepoVal.(string) - - return utils.NewSetupKargoFixtures( - utils.UpdatePromotionTasksVar("promo-process", "gitRepo", kargoDemoRepo), - utils.UpdateWarehouseGitRepoURL("kargo-demo", kargoDemoRepo), - )(ctx, t, cfg) - }) - feature.Teardown(utils.TeardownKargoFixtures) - - feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - t.Logf("Require freight \n") - - anyFreightId, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - t.Logf("Freight: %v", anyFreightId) - return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightId) - }) - - for _, stage := range []string{"test", "uat", "prod"} { - feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - - t.Logf("Promoting %v to %v \n", stage, freightID) - - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - - _, err := utils.PromoteAndWaitForPhase( - ctx, t, - project, stage, freightID, - kargoapi.PromotionPhaseSucceeded, - 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) - - return ctx - }) - } - - utils.TestEnv.Test(t, feature.Feature()) + utils.TestEnv.Test(t, feature()) } diff --git a/hack/test/e2e/suites/argocd_helm_commit_n_image/feature.go b/hack/test/e2e/suites/argocd_helm_commit_n_image/feature.go new file mode 100644 index 0000000000..500affb402 --- /dev/null +++ b/hack/test/e2e/suites/argocd_helm_commit_n_image/feature.go @@ -0,0 +1,99 @@ +//nolint:forcetypeassert +package argocd_helm_commit_n_image + +import ( + "context" + "embed" + "testing" + "time" + + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/hack/test/e2e/envfuncs" + "github.com/akuity/kargo/hack/test/e2e/framework/utils" +) + +func init() { + utils.TestFeatures = append(utils.TestFeatures, feature()) +} + +var ( + //go:embed testdata/* + TestData embed.FS +) + +func feature() features.Feature { + feature := features.New("argocd-helm-commit-n-image") + + // This setup step is necessary to use this feature as a part of shared package test + // It sets the path to look up the fixtures files. + feature.Setup(utils.TestData(TestData)) + + project := "kargo-argocd-helm-commit-image" + origin := "kargo-demo" + + feature.Setup(utils.SetupArgocdClient) + // Point the Argo CD ApplicationSet's source at the fork of the demo GitOps + // repository, mirroring the substitution applied to the Kargo fixtures. + feature.Setup(utils.SetupArgoCDFixturesWithRepoURL(project)) + feature.Teardown(utils.TeardownArgoCDFixtures) + + feature.Setup(utils.SetupKargoClients) + + // Setup and teardown fixtures from testdata folder + feature.Setup(utils.RequireKargoCli) + feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { + kargoDemoRepoVal, err := envfuncs.GetEnv(ctx, []string{"context", "kargo_demo_gitops_repo"}) + if err != nil { + t.Fatalf("cannot get kargo_demo_gitops_repo %v", err) + } + kargoDemoRepo := kargoDemoRepoVal.(string) + + return utils.NewSetupKargoFixtures( + utils.UpdatePromotionTasksVar("promo-process", "gitRepo", kargoDemoRepo), + utils.UpdateWarehouseGitRepoURL("kargo-demo", kargoDemoRepo), + )(ctx, t, cfg) + }) + feature.Teardown(utils.TeardownKargoFixtures) + + feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + t.Logf("Require freight \n") + + anyFreightId, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + t.Logf("Freight: %v", anyFreightId) + return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightId) + }) + + for _, stage := range []string{"test", "uat", "prod"} { + feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + + t.Logf("Promoting %v to %v \n", stage, freightID) + + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + + _, err := utils.PromoteAndWaitForPhase( + ctx, t, + project, stage, freightID, + kargoapi.PromotionPhaseSucceeded, + 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) + + return ctx + }) + } + + return feature.Feature() +} diff --git a/hack/test/e2e/suites/argocd_helm_image_chart_repo/argocd_helm_image_chart_repo_test.go b/hack/test/e2e/suites/argocd_helm_image_chart_repo/argocd_helm_image_chart_repo_test.go index 68846846db..21308d2b2b 100644 --- a/hack/test/e2e/suites/argocd_helm_image_chart_repo/argocd_helm_image_chart_repo_test.go +++ b/hack/test/e2e/suites/argocd_helm_image_chart_repo/argocd_helm_image_chart_repo_test.go @@ -1,25 +1,15 @@ //go:build e2e //nolint:forcetypeassert -package argocd_helm_image_chart_repo_test +package argocd_helm_image_chart_repo // This test implements the Argo CD driven, Helm image-only (with chart repo) // example from https://github.com/akuity/kargo-examples // (01-argocd-driven/02-helm-driven/02-image-only/01-with-chart-repo). -// Stage-specific Argo CD Applications point at a specific version of the nginx -// chart in the Bitnami chart repository and mix in specific versions of the -// public.ecr.aws/nginx/nginx image, which Kargo watches. AnalysisTemplate -// verification is stripped (see testdata/review/verification.yaml). +// Stage-specific Argo CD Applications point at a specific version of the +// chart in the chart repository and mix in specific versions of the image, which Kargo watches. import ( - "context" "testing" - "time" - - "sigs.k8s.io/e2e-framework/pkg/envconf" - "sigs.k8s.io/e2e-framework/pkg/features" - - kargoapi "github.com/akuity/kargo/api/v1alpha1" - "github.com/akuity/kargo/hack/test/e2e/envfuncs" "github.com/akuity/kargo/hack/test/e2e/framework/utils" ) @@ -30,60 +20,5 @@ func TestMain(m *testing.M) { } func TestArgocdHelmImageChartRepo(t *testing.T) { - feature := features.New("argocd-helm-image-chart-repo") - - project := "kargo-argocd-helm-image-chartrepo" - origin := "kargo-demo" - - feature.Setup(utils.SetupArgocdClient) - feature.Setup(utils.SetupArgoCDFixtures) - feature.Teardown(utils.TeardownArgoCDFixtures) - - feature.Setup(utils.SetupKargoClients) - - // Setup and teardown fixtures from testdata folder. - // This example subscribes to a public image registry and a public Helm - // chart repository, so no repo URL substitution is required. - feature.Setup(utils.RequireKargoCli) - feature.Setup(utils.SetupKargoFixtures) - feature.Teardown(utils.TeardownKargoFixtures) - - feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - t.Logf("Require freight \n") - - anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - t.Logf("Freight: %v", anyFreightID) - return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) - }) - - for _, stage := range []string{"test", "uat", "prod"} { - feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - - t.Logf("Promoting %v to %v \n", stage, freightID) - - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - - if _, err := utils.PromoteAndWaitForPhase( - ctx, t, - project, stage, freightID, - kargoapi.PromotionPhaseSucceeded, - 10*time.Minute, - ); err != nil { - t.Fatal(err) - } - - _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) - - return ctx - }) - } - - utils.TestEnv.Test(t, feature.Feature()) + utils.TestEnv.Test(t, feature()) } diff --git a/hack/test/e2e/suites/argocd_helm_image_chart_repo/feature.go b/hack/test/e2e/suites/argocd_helm_image_chart_repo/feature.go new file mode 100644 index 0000000000..59134ad341 --- /dev/null +++ b/hack/test/e2e/suites/argocd_helm_image_chart_repo/feature.go @@ -0,0 +1,88 @@ +//nolint:forcetypeassert +package argocd_helm_image_chart_repo + +import ( + "context" + "embed" + "testing" + "time" + + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/hack/test/e2e/envfuncs" + "github.com/akuity/kargo/hack/test/e2e/framework/utils" +) + +func init() { + utils.TestFeatures = append(utils.TestFeatures, feature()) +} + +var ( + //go:embed testdata/* + TestData embed.FS +) + +func feature() features.Feature { + feature := features.New("argocd-helm-image-chart-repo") + + // This setup step is necessary to use this feature as a part of shared package test + // It sets the path to look up the fixtures files. + feature.Setup(utils.TestData(TestData)) + + project := "kargo-argocd-helm-image-chartrepo" + origin := "kargo-demo" + + feature.Setup(utils.SetupArgocdClient) + feature.Setup(utils.SetupArgoCDFixtures) + feature.Teardown(utils.TeardownArgoCDFixtures) + + feature.Setup(utils.SetupKargoClients) + + // Setup and teardown fixtures from testdata folder. + // This example subscribes to a public image registry and a public Helm + // chart repository, so no repo URL substitution is required. + feature.Setup(utils.RequireKargoCli) + feature.Setup(utils.SetupKargoFixtures) + feature.Teardown(utils.TeardownKargoFixtures) + + feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + t.Logf("Require freight \n") + + anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + t.Logf("Freight: %v", anyFreightID) + return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) + }) + + for _, stage := range []string{"test", "uat", "prod"} { + feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + + t.Logf("Promoting %v to %v \n", stage, freightID) + + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + + if _, err := utils.PromoteAndWaitForPhase( + ctx, t, + project, stage, freightID, + kargoapi.PromotionPhaseSucceeded, + 10*time.Minute, + ); err != nil { + t.Fatal(err) + } + + _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) + + return ctx + }) + } + + return feature.Feature() +} diff --git a/hack/test/e2e/suites/argocd_helm_image_chart_repo/testdata/argocd/argocd.yaml b/hack/test/e2e/suites/argocd_helm_image_chart_repo/testdata/argocd/argocd.yaml index cfc6f4e963..8043d8e710 100644 --- a/hack/test/e2e/suites/argocd_helm_image_chart_repo/testdata/argocd/argocd.yaml +++ b/hack/test/e2e/suites/argocd_helm_image_chart_repo/testdata/argocd/argocd.yaml @@ -18,16 +18,14 @@ spec: spec: project: default source: - repoURL: https://charts.bitnami.com/bitnami - chart: nginx - targetRevision: 14.1.0 + repoURL: https://grafana-community.github.io/helm-charts + chart: grafana + targetRevision: 12.11.2 helm: parameters: # Kargo will update this value to move new images into each stage - name: image.tag value: placeholder - - name: service.type - value: ClusterIP destination: server: https://kubernetes.default.svc namespace: kargo-argocd-helm-image-chartrepo-{{stage}} diff --git a/hack/test/e2e/suites/argocd_helm_image_chart_repo/testdata/kargo/kargo.yaml b/hack/test/e2e/suites/argocd_helm_image_chart_repo/testdata/kargo/kargo.yaml index 3b4b1ad5c7..4a974d3e23 100644 --- a/hack/test/e2e/suites/argocd_helm_image_chart_repo/testdata/kargo/kargo.yaml +++ b/hack/test/e2e/suites/argocd_helm_image_chart_repo/testdata/kargo/kargo.yaml @@ -11,8 +11,8 @@ metadata: spec: subscriptions: - image: - repoURL: public.ecr.aws/nginx/nginx # Watch for new versions of this image - semverConstraint: ^1.24.0 + repoURL: docker.io/grafana/grafana # Watch for new versions of this image + semverConstraint: ^13.0 --- apiVersion: kargo.akuity.io/v1alpha1 kind: PromotionTask @@ -22,15 +22,15 @@ metadata: spec: vars: - name: imageRepo - value: public.ecr.aws/nginx/nginx + value: docker.io/grafana/grafana steps: - uses: argocd-update config: apps: - name: ${{ ctx.project }}-${{ ctx.stage }} sources: - - repoURL: https://charts.bitnami.com/bitnami - chart: nginx + - repoURL: https://grafana-community.github.io/helm-charts + chart: grafana helm: images: - key: image.tag diff --git a/hack/test/e2e/suites/argocd_helm_image_git_repo/argocd_helm_image_git_repo_test.go b/hack/test/e2e/suites/argocd_helm_image_git_repo/argocd_helm_image_git_repo_test.go index f77f507be1..c5aa146d01 100644 --- a/hack/test/e2e/suites/argocd_helm_image_git_repo/argocd_helm_image_git_repo_test.go +++ b/hack/test/e2e/suites/argocd_helm_image_git_repo/argocd_helm_image_git_repo_test.go @@ -1,20 +1,13 @@ //go:build e2e //nolint:forcetypeassert -package argocd_helm_image_git_repo_test +package argocd_helm_image_git_repo // This test implements an example of promoting argocd applications similar to https://github.com/akuity/kargo-examples // The difference is that this example does not have an AnalysisTemplate verification. import ( - "context" "testing" - "time" - "sigs.k8s.io/e2e-framework/pkg/envconf" - "sigs.k8s.io/e2e-framework/pkg/features" - - kargoapi "github.com/akuity/kargo/api/v1alpha1" - "github.com/akuity/kargo/hack/test/e2e/envfuncs" "github.com/akuity/kargo/hack/test/e2e/framework/utils" ) @@ -25,70 +18,5 @@ func TestMain(m *testing.M) { } func TestArgocdHelmImageGitRepo(t *testing.T) { - feature := features.New("argocd-helm-image-git-repo") - - project := "kargo-argocd-helm-image-gitrepo" - origin := "kargo-demo" - - feature.Setup(utils.SetupArgocdClient) - // Point the Argo CD ApplicationSet's source at the fork of the demo GitOps - // repository, mirroring the substitution applied to the Kargo fixtures. - feature.Setup(utils.SetupArgoCDFixturesWithRepoURL(project)) - feature.Teardown(utils.TeardownArgoCDFixtures) - - feature.Setup(utils.SetupKargoClients) - - // Setup and teardown fixtures from testdata folder - feature.Setup(utils.RequireKargoCli) - feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { - kargoDemoRepoVal, err := envfuncs.GetEnv(ctx, []string{"context", "kargo_demo_gitops_repo"}) - if err != nil { - t.Fatalf("cannot get kargo_demo_gitops_repo %v", err) - } - kargoDemoRepo := kargoDemoRepoVal.(string) - - return utils.NewSetupKargoFixtures( - utils.UpdatePromotionTasksVar("promo-process", "gitRepo", kargoDemoRepo), - )(ctx, t, cfg) - }) - feature.Teardown(utils.TeardownKargoFixtures) - - feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - t.Logf("Require freight \n") - - anyFreightId, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - t.Logf("Freight: %v", anyFreightId) - return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightId) - }) - - for _, stage := range []string{"test", "uat", "prod"} { - feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - - t.Logf("Promoting %v to %v \n", stage, freightID) - - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - - _, err := utils.PromoteAndWaitForPhase( - ctx, t, - project, stage, freightID, - kargoapi.PromotionPhaseSucceeded, - 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) - - return ctx - }) - } - - utils.TestEnv.Test(t, feature.Feature()) + utils.TestEnv.Test(t, feature()) } diff --git a/hack/test/e2e/suites/argocd_helm_image_git_repo/feature.go b/hack/test/e2e/suites/argocd_helm_image_git_repo/feature.go new file mode 100644 index 0000000000..5abce720e9 --- /dev/null +++ b/hack/test/e2e/suites/argocd_helm_image_git_repo/feature.go @@ -0,0 +1,98 @@ +//nolint:forcetypeassert +package argocd_helm_image_git_repo + +import ( + "context" + "embed" + "testing" + "time" + + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/hack/test/e2e/envfuncs" + "github.com/akuity/kargo/hack/test/e2e/framework/utils" +) + +func init() { + utils.TestFeatures = append(utils.TestFeatures, feature()) +} + +var ( + //go:embed testdata/* + TestData embed.FS +) + +func feature() features.Feature { + feature := features.New("argocd-helm-image-git-repo") + + // This setup step is necessary to use this feature as a part of shared package test + // It sets the path to look up the fixtures files. + feature.Setup(utils.TestData(TestData)) + + project := "kargo-argocd-helm-image-gitrepo" + origin := "kargo-demo" + + feature.Setup(utils.SetupArgocdClient) + // Point the Argo CD ApplicationSet's source at the fork of the demo GitOps + // repository, mirroring the substitution applied to the Kargo fixtures. + feature.Setup(utils.SetupArgoCDFixturesWithRepoURL(project)) + feature.Teardown(utils.TeardownArgoCDFixtures) + + feature.Setup(utils.SetupKargoClients) + + // Setup and teardown fixtures from testdata folder + feature.Setup(utils.RequireKargoCli) + feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { + kargoDemoRepoVal, err := envfuncs.GetEnv(ctx, []string{"context", "kargo_demo_gitops_repo"}) + if err != nil { + t.Fatalf("cannot get kargo_demo_gitops_repo %v", err) + } + kargoDemoRepo := kargoDemoRepoVal.(string) + + return utils.NewSetupKargoFixtures( + utils.UpdatePromotionTasksVar("promo-process", "gitRepo", kargoDemoRepo), + )(ctx, t, cfg) + }) + feature.Teardown(utils.TeardownKargoFixtures) + + feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + t.Logf("Require freight \n") + + anyFreightId, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + t.Logf("Freight: %v", anyFreightId) + return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightId) + }) + + for _, stage := range []string{"test", "uat", "prod"} { + feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + + t.Logf("Promoting %v to %v \n", stage, freightID) + + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + + _, err := utils.PromoteAndWaitForPhase( + ctx, t, + project, stage, freightID, + kargoapi.PromotionPhaseSucceeded, + 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) + + return ctx + }) + } + + return feature.Feature() +} diff --git a/hack/test/e2e/suites/argocd_kustomize_commit_n_image/argocd_kustomize_commit_n_image_test.go b/hack/test/e2e/suites/argocd_kustomize_commit_n_image/argocd_kustomize_commit_n_image_test.go index 492a1474ed..0fc52b2b0e 100644 --- a/hack/test/e2e/suites/argocd_kustomize_commit_n_image/argocd_kustomize_commit_n_image_test.go +++ b/hack/test/e2e/suites/argocd_kustomize_commit_n_image/argocd_kustomize_commit_n_image_test.go @@ -1,20 +1,13 @@ //go:build e2e //nolint:forcetypeassert -package argocd_kustomize_commit_n_image_test +package argocd_kustomize_commit_n_image // This test implements an example of promoting argocd applications similar to https://github.com/akuity/kargo-examples // The difference is that this example does not have an AnalysisTemplate verification. import ( - "context" "testing" - "time" - "sigs.k8s.io/e2e-framework/pkg/envconf" - "sigs.k8s.io/e2e-framework/pkg/features" - - kargoapi "github.com/akuity/kargo/api/v1alpha1" - "github.com/akuity/kargo/hack/test/e2e/envfuncs" "github.com/akuity/kargo/hack/test/e2e/framework/utils" ) @@ -25,72 +18,5 @@ func TestMain(m *testing.M) { } func TestArgocdKustomizeCommitNImage(t *testing.T) { - feature := features.New("argocd-kustomize-commit-n-image") - - project := "kargo-argocd-kustomize-commit-image" - - feature.Setup(utils.SetupArgocdClient) - // Point the Argo CD ApplicationSet's source at the fork of the demo GitOps - // repository, mirroring the substitution applied to the Kargo fixtures. - feature.Setup(utils.SetupArgoCDFixturesWithRepoURL(project)) - feature.Teardown(utils.TeardownArgoCDFixtures) - - feature.Setup(utils.SetupKargoClients) - - // Setup and teardown fixtures from testdata folder - feature.Setup(utils.RequireKargoCli) - feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { - kargoDemoRepoVal, err := envfuncs.GetEnv(ctx, []string{"context", "kargo_demo_gitops_repo"}) - if err != nil { - t.Fatalf("cannot get kargo_demo_gitops_repo %v", err) - } - kargoDemoRepo := kargoDemoRepoVal.(string) - - return utils.NewSetupKargoFixtures( - utils.UpdatePromotionTasksVar("promo-process", "gitRepo", kargoDemoRepo), - utils.UpdateWarehouseGitRepoURL("kargo-demo", kargoDemoRepo), - )(ctx, t, cfg) - }) - feature.Teardown(utils.TeardownKargoFixtures) - - feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - origin := "kargo-demo" - - t.Logf("Require freight \n") - - anyFreightId, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - t.Logf("Freight: %v", anyFreightId) - return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightId) - }) - - for _, stage := range []string{"test", "uat", "prod"} { - feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - - t.Logf("Promoting %v to %v \n", stage, freightID) - - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - - _, err := utils.PromoteAndWaitForPhase( - ctx, t, - project, stage, freightID, - kargoapi.PromotionPhaseSucceeded, - 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) - - return ctx - }) - } - - utils.TestEnv.Test(t, feature.Feature()) + utils.TestEnv.Test(t, feature()) } diff --git a/hack/test/e2e/suites/argocd_kustomize_commit_n_image/feature.go b/hack/test/e2e/suites/argocd_kustomize_commit_n_image/feature.go new file mode 100644 index 0000000000..55521c7fde --- /dev/null +++ b/hack/test/e2e/suites/argocd_kustomize_commit_n_image/feature.go @@ -0,0 +1,100 @@ +//nolint:forcetypeassert +package argocd_kustomize_commit_n_image + +import ( + "context" + "embed" + "testing" + "time" + + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/hack/test/e2e/envfuncs" + "github.com/akuity/kargo/hack/test/e2e/framework/utils" +) + +func init() { + utils.TestFeatures = append(utils.TestFeatures, feature()) +} + +var ( + //go:embed testdata/* + TestData embed.FS +) + +func feature() features.Feature { + feature := features.New("argocd-kustomize-commit-n-image") + + // This setup step is necessary to use this feature as a part of shared package test + // It sets the path to look up the fixtures files. + feature.Setup(utils.TestData(TestData)) + + project := "kargo-argocd-kustomize-commit-image" + + feature.Setup(utils.SetupArgocdClient) + // Point the Argo CD ApplicationSet's source at the fork of the demo GitOps + // repository, mirroring the substitution applied to the Kargo fixtures. + feature.Setup(utils.SetupArgoCDFixturesWithRepoURL(project)) + feature.Teardown(utils.TeardownArgoCDFixtures) + + feature.Setup(utils.SetupKargoClients) + + // Setup and teardown fixtures from testdata folder + feature.Setup(utils.RequireKargoCli) + feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { + kargoDemoRepoVal, err := envfuncs.GetEnv(ctx, []string{"context", "kargo_demo_gitops_repo"}) + if err != nil { + t.Fatalf("cannot get kargo_demo_gitops_repo %v", err) + } + kargoDemoRepo := kargoDemoRepoVal.(string) + + return utils.NewSetupKargoFixtures( + utils.UpdatePromotionTasksVar("promo-process", "gitRepo", kargoDemoRepo), + utils.UpdateWarehouseGitRepoURL("kargo-demo", kargoDemoRepo), + )(ctx, t, cfg) + }) + feature.Teardown(utils.TeardownKargoFixtures) + + feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + origin := "kargo-demo" + + t.Logf("Require freight \n") + + anyFreightId, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + t.Logf("Freight: %v", anyFreightId) + return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightId) + }) + + for _, stage := range []string{"test", "uat", "prod"} { + feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + + t.Logf("Promoting %v to %v \n", stage, freightID) + + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + + _, err := utils.PromoteAndWaitForPhase( + ctx, t, + project, stage, freightID, + kargoapi.PromotionPhaseSucceeded, + 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) + + return ctx + }) + } + + return feature.Feature() +} diff --git a/hack/test/e2e/suites/argocd_kustomize_image/argocd_kustomize_image_test.go b/hack/test/e2e/suites/argocd_kustomize_image/argocd_kustomize_image_test.go index 8fa9cdfdbd..e5cbee9f4e 100644 --- a/hack/test/e2e/suites/argocd_kustomize_image/argocd_kustomize_image_test.go +++ b/hack/test/e2e/suites/argocd_kustomize_image/argocd_kustomize_image_test.go @@ -1,20 +1,13 @@ //go:build e2e //nolint:forcetypeassert -package argocd_kustomize_image_test +package argocd_kustomize_image // This test implements an example of promoting argocd applications similar to https://github.com/akuity/kargo-examples // The difference is that this example does not have an AnalysisTemplate verification. import ( - "context" "testing" - "time" - "sigs.k8s.io/e2e-framework/pkg/envconf" - "sigs.k8s.io/e2e-framework/pkg/features" - - kargoapi "github.com/akuity/kargo/api/v1alpha1" - "github.com/akuity/kargo/hack/test/e2e/envfuncs" "github.com/akuity/kargo/hack/test/e2e/framework/utils" ) @@ -25,72 +18,5 @@ func TestMain(m *testing.M) { } func TestArgocdKustomizeImage(t *testing.T) { - feature := features.New("argocd-kustomize-image") - - project := "kargo-argocd-kustomize-image" - origin := "kargo-demo" - - feature.Setup(utils.SetupArgocdClient) - // Point the Argo CD ApplicationSet's source at the fork of the demo GitOps - // repository, mirroring the substitution applied to the Kargo fixtures. - feature.Setup(utils.SetupArgoCDFixturesWithRepoURL(project)) - feature.Teardown(utils.TeardownArgoCDFixtures) - - feature.Setup(utils.SetupKargoClients) - - // Setup and teardown fixtures from testdata folder - feature.Setup(utils.RequireKargoCli) - feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { - kargoDemoRepoVal, err := envfuncs.GetEnv(ctx, []string{"context", "kargo_demo_gitops_repo"}) - if err != nil { - t.Fatalf("cannot get kargo_demo_gitops_repo %v", err) - } - kargoDemoRepo := kargoDemoRepoVal.(string) - - // The Warehouse subscribes to an image, so only the PromotionTask's - // gitRepo var needs to point at the fork. - return utils.NewSetupKargoFixtures( - utils.UpdatePromotionTasksVar("promo-process", "gitRepo", kargoDemoRepo), - )(ctx, t, cfg) - }) - feature.Teardown(utils.TeardownKargoFixtures) - - feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - t.Logf("Require freight \n") - - anyFreightId, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - t.Logf("Freight: %v", anyFreightId) - return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightId) - }) - - for _, stage := range []string{"test", "uat", "prod"} { - feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - - t.Logf("Promoting %v to %v \n", stage, freightID) - - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - - _, err := utils.PromoteAndWaitForPhase( - ctx, t, - project, stage, freightID, - kargoapi.PromotionPhaseSucceeded, - 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) - - return ctx - }) - } - - utils.TestEnv.Test(t, feature.Feature()) + utils.TestEnv.Test(t, feature()) } diff --git a/hack/test/e2e/suites/argocd_kustomize_image/feature.go b/hack/test/e2e/suites/argocd_kustomize_image/feature.go new file mode 100644 index 0000000000..e78e824b0b --- /dev/null +++ b/hack/test/e2e/suites/argocd_kustomize_image/feature.go @@ -0,0 +1,100 @@ +//nolint:forcetypeassert +package argocd_kustomize_image + +import ( + "context" + "embed" + "testing" + "time" + + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/hack/test/e2e/envfuncs" + "github.com/akuity/kargo/hack/test/e2e/framework/utils" +) + +func init() { + utils.TestFeatures = append(utils.TestFeatures, feature()) +} + +var ( + //go:embed testdata/* + TestData embed.FS +) + +func feature() features.Feature { + feature := features.New("argocd-kustomize-image") + + // This setup step is necessary to use this feature as a part of shared package test + // It sets the path to look up the fixtures files. + feature.Setup(utils.TestData(TestData)) + + project := "kargo-argocd-kustomize-image" + origin := "kargo-demo" + + feature.Setup(utils.SetupArgocdClient) + // Point the Argo CD ApplicationSet's source at the fork of the demo GitOps + // repository, mirroring the substitution applied to the Kargo fixtures. + feature.Setup(utils.SetupArgoCDFixturesWithRepoURL(project)) + feature.Teardown(utils.TeardownArgoCDFixtures) + + feature.Setup(utils.SetupKargoClients) + + // Setup and teardown fixtures from testdata folder + feature.Setup(utils.RequireKargoCli) + feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { + kargoDemoRepoVal, err := envfuncs.GetEnv(ctx, []string{"context", "kargo_demo_gitops_repo"}) + if err != nil { + t.Fatalf("cannot get kargo_demo_gitops_repo %v", err) + } + kargoDemoRepo := kargoDemoRepoVal.(string) + + // The Warehouse subscribes to an image, so only the PromotionTask's + // gitRepo var needs to point at the fork. + return utils.NewSetupKargoFixtures( + utils.UpdatePromotionTasksVar("promo-process", "gitRepo", kargoDemoRepo), + )(ctx, t, cfg) + }) + feature.Teardown(utils.TeardownKargoFixtures) + + feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + t.Logf("Require freight \n") + + anyFreightId, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + t.Logf("Freight: %v", anyFreightId) + return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightId) + }) + + for _, stage := range []string{"test", "uat", "prod"} { + feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + + t.Logf("Promoting %v to %v \n", stage, freightID) + + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + + _, err := utils.PromoteAndWaitForPhase( + ctx, t, + project, stage, freightID, + kargoapi.PromotionPhaseSucceeded, + 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) + + return ctx + }) + } + + return feature.Feature() +} diff --git a/hack/test/e2e/suites/argocd_update/argocd_update_test.go b/hack/test/e2e/suites/argocd_update/argocd_update_test.go index a1a7462063..be86a97888 100644 --- a/hack/test/e2e/suites/argocd_update/argocd_update_test.go +++ b/hack/test/e2e/suites/argocd_update/argocd_update_test.go @@ -1,21 +1,12 @@ //go:build e2e //nolint:forcetypeassert -package argocd_update_test +package argocd_update // This test implements an example of promoting argocd applications similar to https://github.com/akuity/kargo-examples // The difference is that this example does not have an AnalysisTemplate verification. import ( - "context" "testing" - "time" - - // "github.com/akuity/kargo/pkg/x/client/generated/core" - "sigs.k8s.io/e2e-framework/pkg/envconf" - "sigs.k8s.io/e2e-framework/pkg/features" - - kargoapi "github.com/akuity/kargo/api/v1alpha1" - "github.com/akuity/kargo/hack/test/e2e/envfuncs" "github.com/akuity/kargo/hack/test/e2e/framework/utils" ) @@ -26,118 +17,5 @@ func TestMain(m *testing.M) { } func TestArgocdUpdate(t *testing.T) { - feature := features.New("argocd-update") - - project := "kargo-argocd-update" - - feature.Setup(utils.SetupArgocdClient) - feature.Setup(utils.SetupArgoCDFixturesWithRepoURL(project)) - feature.Teardown(utils.TeardownArgoCDFixtures) - - feature.Setup(utils.SetupKargoClients) - - // Setup and teardown fixtures from testdata folder - feature.Setup(utils.RequireKargoCli) - feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { - kargoDemoRepoVal, err := envfuncs.GetEnv(ctx, []string{"context", "kargo_demo_gitops_repo"}) - if err != nil { - t.Fatalf("cannot get kargo_demo_gitops_repo %v", err) - } - kargoDemoRepo := kargoDemoRepoVal.(string) - - return utils.NewSetupKargoFixtures( - utils.UpdatePromotionTasksVar("promo-process", "gitRepo", kargoDemoRepo), - utils.UpdateWarehouseGitRepoURL("kargo-demo", kargoDemoRepo), - )(ctx, t, cfg) - }) - feature.Teardown(utils.TeardownKargoFixtures) - - feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - origin := "kargo-demo" - - t.Logf("Require freight \n") - - anyFreightId, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - t.Logf("Freight: %v", anyFreightId) - return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightId) - }) - - feature.Assess("promote test", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - stage := "test" - - t.Logf("Promoting test to %v \n", freightID) - - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - - _, err := utils.PromoteAndWaitForPhase( - ctx, t, - project, stage, freightID, - kargoapi.PromotionPhaseSucceeded, - 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) - - return ctx - }) - - feature.Assess("promote uat", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - stage := "uat" - - t.Logf("Promoting uat \n") - - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - - _, err := utils.PromoteAndWaitForPhase( - ctx, t, - project, stage, freightID, - kargoapi.PromotionPhaseSucceeded, - 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) - - return ctx - }) - - feature.Assess("promote prod", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - - stage := "prod" - - t.Logf("Promoting prod \n") - - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - - _, err := utils.PromoteAndWaitForPhase( - ctx, t, - project, stage, freightID, - kargoapi.PromotionPhaseSucceeded, - 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) - - return ctx - }) - - utils.TestEnv.Test(t, feature.Feature()) + utils.TestEnv.Test(t, feature()) } diff --git a/hack/test/e2e/suites/argocd_update/feature.go b/hack/test/e2e/suites/argocd_update/feature.go new file mode 100644 index 0000000000..dcca080b5b --- /dev/null +++ b/hack/test/e2e/suites/argocd_update/feature.go @@ -0,0 +1,146 @@ +//nolint:forcetypeassert +package argocd_update + +import ( + "context" + "embed" + "testing" + "time" + + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/hack/test/e2e/envfuncs" + "github.com/akuity/kargo/hack/test/e2e/framework/utils" +) + +func init() { + utils.TestFeatures = append(utils.TestFeatures, feature()) +} + +var ( + //go:embed testdata/* + TestData embed.FS +) + +func feature() features.Feature { + feature := features.New("argocd-update") + + // This setup step is necessary to use this feature as a part of shared package test + // It sets the path to look up the fixtures files. + feature.Setup(utils.TestData(TestData)) + + project := "kargo-argocd-update" + + feature.Setup(utils.SetupArgocdClient) + feature.Setup(utils.SetupArgoCDFixturesWithRepoURL(project)) + feature.Teardown(utils.TeardownArgoCDFixtures) + + feature.Setup(utils.SetupKargoClients) + + // Setup and teardown fixtures from testdata folder + feature.Setup(utils.RequireKargoCli) + feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { + kargoDemoRepoVal, err := envfuncs.GetEnv(ctx, []string{"context", "kargo_demo_gitops_repo"}) + if err != nil { + t.Fatalf("cannot get kargo_demo_gitops_repo %v", err) + } + kargoDemoRepo := kargoDemoRepoVal.(string) + + return utils.NewSetupKargoFixtures( + utils.UpdatePromotionTasksVar("promo-process", "gitRepo", kargoDemoRepo), + utils.UpdateWarehouseGitRepoURL("kargo-demo", kargoDemoRepo), + )(ctx, t, cfg) + }) + feature.Teardown(utils.TeardownKargoFixtures) + + feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + origin := "kargo-demo" + + t.Logf("Require freight \n") + + anyFreightId, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + t.Logf("Freight: %v", anyFreightId) + return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightId) + }) + + feature.Assess("promote test", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + stage := "test" + + t.Logf("Promoting test to %v \n", freightID) + + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + + _, err := utils.PromoteAndWaitForPhase( + ctx, t, + project, stage, freightID, + kargoapi.PromotionPhaseSucceeded, + 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) + + return ctx + }) + + feature.Assess("promote uat", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + stage := "uat" + + t.Logf("Promoting uat \n") + + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + + _, err := utils.PromoteAndWaitForPhase( + ctx, t, + project, stage, freightID, + kargoapi.PromotionPhaseSucceeded, + 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) + + return ctx + }) + + feature.Assess("promote prod", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + + stage := "prod" + + t.Logf("Promoting prod \n") + + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + + _, err := utils.PromoteAndWaitForPhase( + ctx, t, + project, stage, freightID, + kargoapi.PromotionPhaseSucceeded, + 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) + + return ctx + }) + + return feature.Feature() +} diff --git a/hack/test/e2e/suites/argocd_wait/argocd_wait_test.go b/hack/test/e2e/suites/argocd_wait/argocd_wait_test.go index 8c773d2b33..1d21a6bd13 100644 --- a/hack/test/e2e/suites/argocd_wait/argocd_wait_test.go +++ b/hack/test/e2e/suites/argocd_wait/argocd_wait_test.go @@ -1,6 +1,6 @@ //go:build e2e //nolint:forcetypeassert -package argocd_wait_test +package argocd_wait // This test exercises the argocd-wait promotion step. A branch is created in // test setup (as a copy of the kustomize branch); the Argo CD Application tracks @@ -11,16 +11,8 @@ package argocd_wait_test // does -- which is exactly the scenario argocd-wait exists for. import ( - "context" - "fmt" "testing" - "time" - "sigs.k8s.io/e2e-framework/pkg/envconf" - "sigs.k8s.io/e2e-framework/pkg/features" - - kargoapi "github.com/akuity/kargo/api/v1alpha1" - "github.com/akuity/kargo/hack/test/e2e/envfuncs" "github.com/akuity/kargo/hack/test/e2e/framework/utils" ) @@ -31,95 +23,5 @@ func TestMain(m *testing.M) { } func TestArgocdWait(t *testing.T) { - feature := features.New("argocd-wait") - - project := "kargo-argocd-wait" - origin := "kargo-demo" - stage := "test" - - // Branch created uniquely per test run. Both the Argo CD Application's - // targetRevision and the promotion's targetBranch var point at it. - branch := fmt.Sprintf("argocd-wait/e2e/%d", time.Now().UnixNano()) - - // Create the branch (a copy of the kustomize branch) BEFORE Argo CD is set - // up, so the Application has an existing branch to track. - feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { - creds := utils.RequireGitCreds(ctx, t) - t.Logf("Git creds %v", creds) - - if err := utils.CreateRemoteBranch(ctx, creds.RepoURL, creds.Password, branch, "kustomize"); err != nil { - t.Fatalf("failed to create branch %q: %v", branch, err) - } - t.Logf("created branch %q", branch) - return ctx - }) - - feature.Setup(utils.SetupArgocdClient) - // Point the Argo CD ApplicationSet at the fork and the per-run branch. - feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { - repoVal, err := envfuncs.GetEnv(ctx, []string{"context", "kargo_demo_gitops_repo"}) - if err != nil { - t.Fatalf("cannot get kargo_demo_gitops_repo %v", err) - } - repo := repoVal.(string) - - return utils.NewSetupArgoCDFixtures( - utils.UpdateApplicationSetRepoURL(project, repo), - utils.UpdateApplicationSetTargetRevision(project, branch), - )(ctx, t, cfg) - }) - feature.Teardown(utils.TeardownArgoCDFixtures) - - feature.Setup(utils.SetupKargoClients) - - // Substitute the git credentials Secret, the promotion's gitRepo var and the - // per-run targetBranch. The Warehouse subscribes to an image, so no Warehouse - // git repo URL substitution is applied. - feature.Setup(utils.RequireKargoCli) - feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { - creds := utils.RequireGitCreds(ctx, t) - return utils.NewSetupKargoFixtures( - utils.UpdateGitCredentialsSecret("manifests", creds.RepoURL, creds.Username, creds.Password), - utils.UpdateStagePromotionVar("", "gitRepo", creds.RepoURL), - utils.UpdateStagePromotionVar("", "targetBranch", branch), - )(ctx, t, cfg) - }) - feature.Teardown(utils.TeardownKargoFixtures) - - feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - t.Logf("Require freight \n") - - anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - t.Logf("Freight: %v", anyFreightID) - return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) - }) - - feature.Assess("promotion waits for argocd to reconcile", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - - t.Logf("Promoting %v to %v on branch %q \n", stage, freightID, branch) - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - - // The argocd-wait step keeps the promotion Running until Argo CD reports - // the Application Healthy and Synced, so reaching Succeeded means the - // pushed change was reconciled. - if _, err := utils.PromoteAndWaitForPhase( - ctx, t, - project, stage, freightID, - kargoapi.PromotionPhaseSucceeded, - 15*time.Minute, - ); err != nil { - t.Fatal(err) - } - - return ctx - }) - - utils.TestEnv.Test(t, feature.Feature()) + utils.TestEnv.Test(t, feature()) } diff --git a/hack/test/e2e/suites/argocd_wait/feature.go b/hack/test/e2e/suites/argocd_wait/feature.go new file mode 100644 index 0000000000..2152a8cc5c --- /dev/null +++ b/hack/test/e2e/suites/argocd_wait/feature.go @@ -0,0 +1,125 @@ +//nolint:forcetypeassert +package argocd_wait + +import ( + "context" + "embed" + "fmt" + "testing" + "time" + + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/hack/test/e2e/envfuncs" + "github.com/akuity/kargo/hack/test/e2e/framework/utils" +) + +func init() { + utils.TestFeatures = append(utils.TestFeatures, feature()) +} + +var ( + //go:embed testdata/* + TestData embed.FS +) + +func feature() features.Feature { + feature := features.New("argocd-wait") + + project := "kargo-argocd-wait" + origin := "kargo-demo" + stage := "test" + + // Branch created uniquely per test run. Both the Argo CD Application's + // targetRevision and the promotion's targetBranch var point at it. + branch := fmt.Sprintf("argocd-wait/e2e/%d", time.Now().UnixNano()) + + // This setup step is necessary to use this feature as a part of shared package test + // It sets the path to look up the fixtures files. + feature.Setup(utils.TestData(TestData)) + + // Create the branch (a copy of the kustomize branch) BEFORE Argo CD is set + // up, so the Application has an existing branch to track. + feature.Setup(func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + creds := utils.RequireGitCreds(ctx, t) + t.Logf("Git creds %v", creds) + + if err := utils.CreateRemoteBranch(ctx, creds.RepoURL, creds.Password, branch, "kustomize"); err != nil { + t.Fatalf("failed to create branch %q: %v", branch, err) + } + t.Logf("created branch %q", branch) + return ctx + }) + + feature.Setup(utils.SetupArgocdClient) + // Point the Argo CD ApplicationSet at the fork and the per-run branch. + feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { + repoVal, err := envfuncs.GetEnv(ctx, []string{"context", "kargo_demo_gitops_repo"}) + if err != nil { + t.Fatalf("cannot get kargo_demo_gitops_repo %v", err) + } + repo := repoVal.(string) + + return utils.NewSetupArgoCDFixtures( + utils.UpdateApplicationSetRepoURL(project, repo), + utils.UpdateApplicationSetTargetRevision(project, branch), + )(ctx, t, cfg) + }) + feature.Teardown(utils.TeardownArgoCDFixtures) + + feature.Setup(utils.SetupKargoClients) + + // Substitute the git credentials Secret, the promotion's gitRepo var and the + // per-run targetBranch. The Warehouse subscribes to an image, so no Warehouse + // git repo URL substitution is applied. + feature.Setup(utils.RequireKargoCli) + feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { + creds := utils.RequireGitCreds(ctx, t) + return utils.NewSetupKargoFixtures( + utils.UpdateGitCredentialsSecret("manifests", creds.RepoURL, creds.Username, creds.Password), + utils.UpdateStagePromotionVar("", "gitRepo", creds.RepoURL), + utils.UpdateStagePromotionVar("", "targetBranch", branch), + )(ctx, t, cfg) + }) + feature.Teardown(utils.TeardownKargoFixtures) + + feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + t.Logf("Require freight \n") + + anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + t.Logf("Freight: %v", anyFreightID) + return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) + }) + + feature.Assess("promotion waits for argocd to reconcile", + func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + + t.Logf("Promoting %v to %v on branch %q \n", stage, freightID, branch) + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + + // The argocd-wait step keeps the promotion Running until Argo CD reports + // the Application Healthy and Synced, so reaching Succeeded means the + // pushed change was reconciled. + if _, err := utils.PromoteAndWaitForPhase( + ctx, t, + project, stage, freightID, + kargoapi.PromotionPhaseSucceeded, + 15*time.Minute, + ); err != nil { + t.Fatal(err) + } + + return ctx + }) + + return feature.Feature() +} diff --git a/hack/test/e2e/suites/git_commit_only/feature.go b/hack/test/e2e/suites/git_commit_only/feature.go new file mode 100644 index 0000000000..c0a02fb786 --- /dev/null +++ b/hack/test/e2e/suites/git_commit_only/feature.go @@ -0,0 +1,124 @@ +//nolint:forcetypeassert +package git_commit_only + +import ( + "context" + "embed" + "testing" + "time" + + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/hack/test/e2e/envfuncs" + "github.com/akuity/kargo/hack/test/e2e/framework/utils" +) + +func init() { + utils.TestFeatures = append(utils.TestFeatures, feature()) +} + +var ( + //go:embed testdata/* + TestData embed.FS +) + +func feature() features.Feature { + feature := features.New("git-commit-only") + + // This setup step is necessary to use this feature as a part of shared package test + // It sets the path to look up the fixtures files. + feature.Setup(utils.TestData(TestData)) + + project := "kargo-git-commit-only" + origin := "kargo-demo" + + feature.Setup(utils.SetupArgocdClient) + // Point the Argo CD ApplicationSet's source at the fork of the demo GitOps + // repository, mirroring the substitution applied to the Kargo fixtures. + feature.Setup(utils.SetupArgoCDFixturesWithRepoURL(project)) + feature.Teardown(utils.TeardownArgoCDFixtures) + + feature.Setup(utils.SetupKargoClients) + + // Setup and teardown fixtures from testdata folder. Substitute the git + // credentials Secret, the per-Stage gitRepo var and the Warehouse git + // subscription with the fork and PAT from the test env. + feature.Setup(utils.RequireKargoCli) + feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { + creds := utils.RequireGitCreds(ctx, t) + return utils.NewSetupKargoFixtures( + utils.UpdateGitCredentialsSecret("manifests", creds.RepoURL, creds.Username, creds.Password), + utils.UpdateStagePromotionVar("", "gitRepo", creds.RepoURL), + utils.UpdateWarehouseGitRepoURL("kargo-demo", creds.RepoURL), + )(ctx, t, cfg) + }) + feature.Teardown(utils.TeardownKargoFixtures) + + feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + t.Logf("Require freight \n") + + anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + t.Logf("Freight: %v", anyFreightID) + return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) + }) + + // test and uat push directly to their stage branches; prod is handled + // separately below because it is gated on a pull request merge. + for _, stage := range []string{"test", "uat"} { + feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + + t.Logf("Promoting %v to %v \n", stage, freightID) + + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + + if _, err := utils.PromoteAndWaitForPhase( + ctx, t, + project, stage, freightID, + kargoapi.PromotionPhaseSucceeded, + 10*time.Minute, + ); err != nil { + t.Fatal(err) + } + + _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) + + return ctx + }) + } + + feature.Assess("promote prod", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + creds := utils.RequireGitCreds(ctx, t) + stage := "prod" + + t.Logf("Promoting prod (merging its pull request) to %v \n", freightID) + + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + + if _, err := utils.PromoteWithPRMerge( + ctx, t, + project, stage, freightID, + creds.RepoURL, creds.Password, "open-pr", + 15*time.Minute, + ); err != nil { + t.Fatal(err) + } + + _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) + + return ctx + }) + + return feature.Feature() +} diff --git a/hack/test/e2e/suites/git_commit_only/git_commit_only_test.go b/hack/test/e2e/suites/git_commit_only/git_commit_only_test.go index 10c875e8ee..4a30bcf042 100644 --- a/hack/test/e2e/suites/git_commit_only/git_commit_only_test.go +++ b/hack/test/e2e/suites/git_commit_only/git_commit_only_test.go @@ -1,6 +1,6 @@ //go:build e2e //nolint:forcetypeassert -package git_commit_only_test +package git_commit_only // This test implements the Git driven, commit-only example from // https://github.com/akuity/kargo-examples (02-git-driven/01-commit-only). @@ -14,15 +14,7 @@ package git_commit_only_test // (see testdata/review/verification.yaml). import ( - "context" "testing" - "time" - - "sigs.k8s.io/e2e-framework/pkg/envconf" - "sigs.k8s.io/e2e-framework/pkg/features" - - kargoapi "github.com/akuity/kargo/api/v1alpha1" - "github.com/akuity/kargo/hack/test/e2e/envfuncs" "github.com/akuity/kargo/hack/test/e2e/framework/utils" ) @@ -33,96 +25,5 @@ func TestMain(m *testing.M) { } func TestGitCommitOnly(t *testing.T) { - feature := features.New("git-commit-only") - - project := "kargo-git-commit-only" - origin := "kargo-demo" - - feature.Setup(utils.SetupArgocdClient) - // Point the Argo CD ApplicationSet's source at the fork of the demo GitOps - // repository, mirroring the substitution applied to the Kargo fixtures. - feature.Setup(utils.SetupArgoCDFixturesWithRepoURL(project)) - feature.Teardown(utils.TeardownArgoCDFixtures) - - feature.Setup(utils.SetupKargoClients) - - // Setup and teardown fixtures from testdata folder. Substitute the git - // credentials Secret, the per-Stage gitRepo var and the Warehouse git - // subscription with the fork and PAT from the test env. - feature.Setup(utils.RequireKargoCli) - feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { - creds := utils.RequireGitCreds(ctx, t) - return utils.NewSetupKargoFixtures( - utils.UpdateGitCredentialsSecret("manifests", creds.RepoURL, creds.Username, creds.Password), - utils.UpdateStagePromotionVar("", "gitRepo", creds.RepoURL), - utils.UpdateWarehouseGitRepoURL("kargo-demo", creds.RepoURL), - )(ctx, t, cfg) - }) - feature.Teardown(utils.TeardownKargoFixtures) - - feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - t.Logf("Require freight \n") - - anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - t.Logf("Freight: %v", anyFreightID) - return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) - }) - - // test and uat push directly to their stage branches; prod is handled - // separately below because it is gated on a pull request merge. - for _, stage := range []string{"test", "uat"} { - feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - - t.Logf("Promoting %v to %v \n", stage, freightID) - - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - - if _, err := utils.PromoteAndWaitForPhase( - ctx, t, - project, stage, freightID, - kargoapi.PromotionPhaseSucceeded, - 10*time.Minute, - ); err != nil { - t.Fatal(err) - } - - _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) - - return ctx - }) - } - - feature.Assess("promote prod", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - creds := utils.RequireGitCreds(ctx, t) - stage := "prod" - - t.Logf("Promoting prod (merging its pull request) to %v \n", freightID) - - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - - if _, err := utils.PromoteWithPRMerge( - ctx, t, - project, stage, freightID, - creds.RepoURL, creds.Password, "open-pr", - 15*time.Minute, - ); err != nil { - t.Fatal(err) - } - - _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) - - return ctx - }) - - utils.TestEnv.Test(t, feature.Feature()) + utils.TestEnv.Test(t, feature()) } diff --git a/hack/test/e2e/suites/git_helm_commit_n_image/feature.go b/hack/test/e2e/suites/git_helm_commit_n_image/feature.go new file mode 100644 index 0000000000..2cb25054eb --- /dev/null +++ b/hack/test/e2e/suites/git_helm_commit_n_image/feature.go @@ -0,0 +1,124 @@ +//nolint:forcetypeassert +package git_helm_commit_n_image + +import ( + "context" + "embed" + "testing" + "time" + + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/hack/test/e2e/envfuncs" + "github.com/akuity/kargo/hack/test/e2e/framework/utils" +) + +func init() { + utils.TestFeatures = append(utils.TestFeatures, feature()) +} + +var ( + //go:embed testdata/* + TestData embed.FS +) + +func feature() features.Feature { + feature := features.New("git-helm-commit-n-image") + + // This setup step is necessary to use this feature as a part of shared package test + // It sets the path to look up the fixtures files. + feature.Setup(utils.TestData(TestData)) + + project := "kargo-git-helm-commit-image" + origin := "kargo-demo" + + feature.Setup(utils.SetupArgocdClient) + // Point the Argo CD ApplicationSet's source at the fork of the demo GitOps + // repository, mirroring the substitution applied to the Kargo fixtures. + feature.Setup(utils.SetupArgoCDFixturesWithRepoURL(project)) + feature.Teardown(utils.TeardownArgoCDFixtures) + + feature.Setup(utils.SetupKargoClients) + + // Setup and teardown fixtures from testdata folder. Substitute the git + // credentials Secret, the per-Stage gitRepo var and the Warehouse git + // subscription with the fork and PAT from the test env. + feature.Setup(utils.RequireKargoCli) + feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { + creds := utils.RequireGitCreds(ctx, t) + return utils.NewSetupKargoFixtures( + utils.UpdateGitCredentialsSecret("manifests", creds.RepoURL, creds.Username, creds.Password), + utils.UpdateStagePromotionVar("", "gitRepo", creds.RepoURL), + utils.UpdateWarehouseGitRepoURL("kargo-demo", creds.RepoURL), + )(ctx, t, cfg) + }) + feature.Teardown(utils.TeardownKargoFixtures) + + feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + t.Logf("Require freight \n") + + anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + t.Logf("Freight: %v", anyFreightID) + return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) + }) + + // test and uat push directly to their stage branches; prod is handled + // separately below because it is gated on a pull request merge. + for _, stage := range []string{"test", "uat"} { + feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + + t.Logf("Promoting %v to %v \n", stage, freightID) + + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + + if _, err := utils.PromoteAndWaitForPhase( + ctx, t, + project, stage, freightID, + kargoapi.PromotionPhaseSucceeded, + 10*time.Minute, + ); err != nil { + t.Fatal(err) + } + + _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) + + return ctx + }) + } + + feature.Assess("promote prod", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + creds := utils.RequireGitCreds(ctx, t) + stage := "prod" + + t.Logf("Promoting prod (merging its pull request) to %v \n", freightID) + + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + + if _, err := utils.PromoteWithPRMerge( + ctx, t, + project, stage, freightID, + creds.RepoURL, creds.Password, "open-pr", + 15*time.Minute, + ); err != nil { + t.Fatal(err) + } + + _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) + + return ctx + }) + + return feature.Feature() +} diff --git a/hack/test/e2e/suites/git_helm_commit_n_image/git_helm_commit_n_image_test.go b/hack/test/e2e/suites/git_helm_commit_n_image/git_helm_commit_n_image_test.go index ff320f0368..049326151e 100644 --- a/hack/test/e2e/suites/git_helm_commit_n_image/git_helm_commit_n_image_test.go +++ b/hack/test/e2e/suites/git_helm_commit_n_image/git_helm_commit_n_image_test.go @@ -1,6 +1,6 @@ //go:build e2e //nolint:forcetypeassert -package git_helm_commit_n_image_test +package git_helm_commit_n_image // This test implements the Git driven, Helm driven, commit-n-image example from // https://github.com/akuity/kargo-examples @@ -16,15 +16,8 @@ package git_helm_commit_n_image_test // (see testdata/review/verification.yaml). import ( - "context" "testing" - "time" - "sigs.k8s.io/e2e-framework/pkg/envconf" - "sigs.k8s.io/e2e-framework/pkg/features" - - kargoapi "github.com/akuity/kargo/api/v1alpha1" - "github.com/akuity/kargo/hack/test/e2e/envfuncs" "github.com/akuity/kargo/hack/test/e2e/framework/utils" ) @@ -35,96 +28,5 @@ func TestMain(m *testing.M) { } func TestGitHelmCommitNImage(t *testing.T) { - feature := features.New("git-helm-commit-n-image") - - project := "kargo-git-helm-commit-image" - origin := "kargo-demo" - - feature.Setup(utils.SetupArgocdClient) - // Point the Argo CD ApplicationSet's source at the fork of the demo GitOps - // repository, mirroring the substitution applied to the Kargo fixtures. - feature.Setup(utils.SetupArgoCDFixturesWithRepoURL(project)) - feature.Teardown(utils.TeardownArgoCDFixtures) - - feature.Setup(utils.SetupKargoClients) - - // Setup and teardown fixtures from testdata folder. Substitute the git - // credentials Secret, the per-Stage gitRepo var and the Warehouse git - // subscription with the fork and PAT from the test env. - feature.Setup(utils.RequireKargoCli) - feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { - creds := utils.RequireGitCreds(ctx, t) - return utils.NewSetupKargoFixtures( - utils.UpdateGitCredentialsSecret("manifests", creds.RepoURL, creds.Username, creds.Password), - utils.UpdateStagePromotionVar("", "gitRepo", creds.RepoURL), - utils.UpdateWarehouseGitRepoURL("kargo-demo", creds.RepoURL), - )(ctx, t, cfg) - }) - feature.Teardown(utils.TeardownKargoFixtures) - - feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - t.Logf("Require freight \n") - - anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - t.Logf("Freight: %v", anyFreightID) - return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) - }) - - // test and uat push directly to their stage branches; prod is handled - // separately below because it is gated on a pull request merge. - for _, stage := range []string{"test", "uat"} { - feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - - t.Logf("Promoting %v to %v \n", stage, freightID) - - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - - if _, err := utils.PromoteAndWaitForPhase( - ctx, t, - project, stage, freightID, - kargoapi.PromotionPhaseSucceeded, - 10*time.Minute, - ); err != nil { - t.Fatal(err) - } - - _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) - - return ctx - }) - } - - feature.Assess("promote prod", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - creds := utils.RequireGitCreds(ctx, t) - stage := "prod" - - t.Logf("Promoting prod (merging its pull request) to %v \n", freightID) - - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - - if _, err := utils.PromoteWithPRMerge( - ctx, t, - project, stage, freightID, - creds.RepoURL, creds.Password, "open-pr", - 15*time.Minute, - ); err != nil { - t.Fatal(err) - } - - _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) - - return ctx - }) - - utils.TestEnv.Test(t, feature.Feature()) + utils.TestEnv.Test(t, feature()) } diff --git a/hack/test/e2e/suites/git_helm_image/feature.go b/hack/test/e2e/suites/git_helm_image/feature.go new file mode 100644 index 0000000000..24d1b438ce --- /dev/null +++ b/hack/test/e2e/suites/git_helm_image/feature.go @@ -0,0 +1,124 @@ +//nolint:forcetypeassert +package git_helm_image + +import ( + "context" + "embed" + "testing" + "time" + + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/hack/test/e2e/envfuncs" + "github.com/akuity/kargo/hack/test/e2e/framework/utils" +) + +func init() { + utils.TestFeatures = append(utils.TestFeatures, feature()) +} + +var ( + //go:embed testdata/* + TestData embed.FS +) + +func feature() features.Feature { + feature := features.New("git-helm-image") + + // This setup step is necessary to use this feature as a part of shared package test + // It sets the path to look up the fixtures files. + feature.Setup(utils.TestData(TestData)) + + project := "kargo-git-helm-image" + origin := "kargo-demo" + + feature.Setup(utils.SetupArgocdClient) + // Point the Argo CD ApplicationSet's source at the fork of the demo GitOps + // repository, mirroring the substitution applied to the Kargo fixtures. + feature.Setup(utils.SetupArgoCDFixturesWithRepoURL(project)) + feature.Teardown(utils.TeardownArgoCDFixtures) + + feature.Setup(utils.SetupKargoClients) + + // Setup and teardown fixtures from testdata folder. Substitute the git + // credentials Secret and the per-Stage gitRepo var with the fork and PAT + // from the test env. The Warehouse subscribes to an image, not git, so no + // git repo URL substitution is applied to it. + feature.Setup(utils.RequireKargoCli) + feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { + creds := utils.RequireGitCreds(ctx, t) + return utils.NewSetupKargoFixtures( + utils.UpdateGitCredentialsSecret("manifests", creds.RepoURL, creds.Username, creds.Password), + utils.UpdateStagePromotionVar("", "gitRepo", creds.RepoURL), + )(ctx, t, cfg) + }) + feature.Teardown(utils.TeardownKargoFixtures) + + feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + t.Logf("Require freight \n") + + anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + t.Logf("Freight: %v", anyFreightID) + return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) + }) + + // test and uat push directly to their stage branches; prod is handled + // separately below because it is gated on a pull request merge. + for _, stage := range []string{"test", "uat"} { + feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + + t.Logf("Promoting %v to %v \n", stage, freightID) + + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + + if _, err := utils.PromoteAndWaitForPhase( + ctx, t, + project, stage, freightID, + kargoapi.PromotionPhaseSucceeded, + 10*time.Minute, + ); err != nil { + t.Fatal(err) + } + + _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) + + return ctx + }) + } + + feature.Assess("promote prod", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + creds := utils.RequireGitCreds(ctx, t) + stage := "prod" + + t.Logf("Promoting prod (merging its pull request) to %v \n", freightID) + + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + + if _, err := utils.PromoteWithPRMerge( + ctx, t, + project, stage, freightID, + creds.RepoURL, creds.Password, "open-pr", + 15*time.Minute, + ); err != nil { + t.Fatal(err) + } + + _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) + + return ctx + }) + + return feature.Feature() +} diff --git a/hack/test/e2e/suites/git_helm_image/git_helm_image_test.go b/hack/test/e2e/suites/git_helm_image/git_helm_image_test.go index ee4929bdcd..947c79c1a9 100644 --- a/hack/test/e2e/suites/git_helm_image/git_helm_image_test.go +++ b/hack/test/e2e/suites/git_helm_image/git_helm_image_test.go @@ -1,6 +1,6 @@ //go:build e2e //nolint:forcetypeassert -package git_helm_image_test +package git_helm_image // This test implements the Git driven, Helm-based image-only example from // https://github.com/akuity/kargo-examples @@ -16,15 +16,7 @@ package git_helm_image_test // (see testdata/review/verification.yaml). import ( - "context" "testing" - "time" - - "sigs.k8s.io/e2e-framework/pkg/envconf" - "sigs.k8s.io/e2e-framework/pkg/features" - - kargoapi "github.com/akuity/kargo/api/v1alpha1" - "github.com/akuity/kargo/hack/test/e2e/envfuncs" "github.com/akuity/kargo/hack/test/e2e/framework/utils" ) @@ -35,96 +27,5 @@ func TestMain(m *testing.M) { } func TestGitHelmImage(t *testing.T) { - feature := features.New("git-helm-image") - - project := "kargo-git-helm-image" - origin := "kargo-demo" - - feature.Setup(utils.SetupArgocdClient) - // Point the Argo CD ApplicationSet's source at the fork of the demo GitOps - // repository, mirroring the substitution applied to the Kargo fixtures. - feature.Setup(utils.SetupArgoCDFixturesWithRepoURL(project)) - feature.Teardown(utils.TeardownArgoCDFixtures) - - feature.Setup(utils.SetupKargoClients) - - // Setup and teardown fixtures from testdata folder. Substitute the git - // credentials Secret and the per-Stage gitRepo var with the fork and PAT - // from the test env. The Warehouse subscribes to an image, not git, so no - // git repo URL substitution is applied to it. - feature.Setup(utils.RequireKargoCli) - feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { - creds := utils.RequireGitCreds(ctx, t) - return utils.NewSetupKargoFixtures( - utils.UpdateGitCredentialsSecret("manifests", creds.RepoURL, creds.Username, creds.Password), - utils.UpdateStagePromotionVar("", "gitRepo", creds.RepoURL), - )(ctx, t, cfg) - }) - feature.Teardown(utils.TeardownKargoFixtures) - - feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - t.Logf("Require freight \n") - - anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - t.Logf("Freight: %v", anyFreightID) - return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) - }) - - // test and uat push directly to their stage branches; prod is handled - // separately below because it is gated on a pull request merge. - for _, stage := range []string{"test", "uat"} { - feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - - t.Logf("Promoting %v to %v \n", stage, freightID) - - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - - if _, err := utils.PromoteAndWaitForPhase( - ctx, t, - project, stage, freightID, - kargoapi.PromotionPhaseSucceeded, - 10*time.Minute, - ); err != nil { - t.Fatal(err) - } - - _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) - - return ctx - }) - } - - feature.Assess("promote prod", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - creds := utils.RequireGitCreds(ctx, t) - stage := "prod" - - t.Logf("Promoting prod (merging its pull request) to %v \n", freightID) - - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - - if _, err := utils.PromoteWithPRMerge( - ctx, t, - project, stage, freightID, - creds.RepoURL, creds.Password, "open-pr", - 15*time.Minute, - ); err != nil { - t.Fatal(err) - } - - _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) - - return ctx - }) - - utils.TestEnv.Test(t, feature.Feature()) + utils.TestEnv.Test(t, feature()) } diff --git a/hack/test/e2e/suites/git_kustomize_commit_n_image/feature.go b/hack/test/e2e/suites/git_kustomize_commit_n_image/feature.go new file mode 100644 index 0000000000..4e0f248866 --- /dev/null +++ b/hack/test/e2e/suites/git_kustomize_commit_n_image/feature.go @@ -0,0 +1,124 @@ +//nolint:forcetypeassert +package git_kustomize_commit_n_image + +import ( + "context" + "embed" + "testing" + "time" + + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/hack/test/e2e/envfuncs" + "github.com/akuity/kargo/hack/test/e2e/framework/utils" +) + +func init() { + utils.TestFeatures = append(utils.TestFeatures, feature()) +} + +var ( + //go:embed testdata/* + TestData embed.FS +) + +func feature() features.Feature { + feature := features.New("git-kustomize-commit-n-image") + + // This setup step is necessary to use this feature as a part of shared package test + // It sets the path to look up the fixtures files. + feature.Setup(utils.TestData(TestData)) + + project := "kargo-git-kustomize-commit-image" + origin := "kargo-demo" + + feature.Setup(utils.SetupArgocdClient) + // Point the Argo CD ApplicationSet's source at the fork of the demo GitOps + // repository, mirroring the substitution applied to the Kargo fixtures. + feature.Setup(utils.SetupArgoCDFixturesWithRepoURL(project)) + feature.Teardown(utils.TeardownArgoCDFixtures) + + feature.Setup(utils.SetupKargoClients) + + // Setup and teardown fixtures from testdata folder. Substitute the git + // credentials Secret, the per-Stage gitRepo var and the Warehouse git + // subscription with the fork and PAT from the test env. + feature.Setup(utils.RequireKargoCli) + feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { + creds := utils.RequireGitCreds(ctx, t) + return utils.NewSetupKargoFixtures( + utils.UpdateGitCredentialsSecret("manifests", creds.RepoURL, creds.Username, creds.Password), + utils.UpdateStagePromotionVar("", "gitRepo", creds.RepoURL), + utils.UpdateWarehouseGitRepoURL("kargo-demo", creds.RepoURL), + )(ctx, t, cfg) + }) + feature.Teardown(utils.TeardownKargoFixtures) + + feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + t.Logf("Require freight \n") + + anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + t.Logf("Freight: %v", anyFreightID) + return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) + }) + + // test and uat push directly to their stage branches; prod is handled + // separately below because it is gated on a pull request merge. + for _, stage := range []string{"test", "uat"} { + feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + + t.Logf("Promoting %v to %v \n", stage, freightID) + + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + + if _, err := utils.PromoteAndWaitForPhase( + ctx, t, + project, stage, freightID, + kargoapi.PromotionPhaseSucceeded, + 10*time.Minute, + ); err != nil { + t.Fatal(err) + } + + _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) + + return ctx + }) + } + + feature.Assess("promote prod", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + creds := utils.RequireGitCreds(ctx, t) + stage := "prod" + + t.Logf("Promoting prod (merging its pull request) to %v \n", freightID) + + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + + if _, err := utils.PromoteWithPRMerge( + ctx, t, + project, stage, freightID, + creds.RepoURL, creds.Password, "open-pr", + 15*time.Minute, + ); err != nil { + t.Fatal(err) + } + + _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) + + return ctx + }) + + return feature.Feature() +} diff --git a/hack/test/e2e/suites/git_kustomize_commit_n_image/git_kustomize_commit_n_image_test.go b/hack/test/e2e/suites/git_kustomize_commit_n_image/git_kustomize_commit_n_image_test.go index 5282855874..8fb9989fbe 100644 --- a/hack/test/e2e/suites/git_kustomize_commit_n_image/git_kustomize_commit_n_image_test.go +++ b/hack/test/e2e/suites/git_kustomize_commit_n_image/git_kustomize_commit_n_image_test.go @@ -1,6 +1,6 @@ //go:build e2e //nolint:forcetypeassert -package git_kustomize_commit_n_image_test +package git_kustomize_commit_n_image // This test implements the Git driven, kustomize commit-n-image example from // https://github.com/akuity/kargo-examples @@ -16,15 +16,8 @@ package git_kustomize_commit_n_image_test // (see testdata/review/verification.yaml). import ( - "context" "testing" - "time" - "sigs.k8s.io/e2e-framework/pkg/envconf" - "sigs.k8s.io/e2e-framework/pkg/features" - - kargoapi "github.com/akuity/kargo/api/v1alpha1" - "github.com/akuity/kargo/hack/test/e2e/envfuncs" "github.com/akuity/kargo/hack/test/e2e/framework/utils" ) @@ -35,96 +28,5 @@ func TestMain(m *testing.M) { } func TestGitKustomizeCommitNImage(t *testing.T) { - feature := features.New("git-kustomize-commit-n-image") - - project := "kargo-git-kustomize-commit-image" - origin := "kargo-demo" - - feature.Setup(utils.SetupArgocdClient) - // Point the Argo CD ApplicationSet's source at the fork of the demo GitOps - // repository, mirroring the substitution applied to the Kargo fixtures. - feature.Setup(utils.SetupArgoCDFixturesWithRepoURL(project)) - feature.Teardown(utils.TeardownArgoCDFixtures) - - feature.Setup(utils.SetupKargoClients) - - // Setup and teardown fixtures from testdata folder. Substitute the git - // credentials Secret, the per-Stage gitRepo var and the Warehouse git - // subscription with the fork and PAT from the test env. - feature.Setup(utils.RequireKargoCli) - feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { - creds := utils.RequireGitCreds(ctx, t) - return utils.NewSetupKargoFixtures( - utils.UpdateGitCredentialsSecret("manifests", creds.RepoURL, creds.Username, creds.Password), - utils.UpdateStagePromotionVar("", "gitRepo", creds.RepoURL), - utils.UpdateWarehouseGitRepoURL("kargo-demo", creds.RepoURL), - )(ctx, t, cfg) - }) - feature.Teardown(utils.TeardownKargoFixtures) - - feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - t.Logf("Require freight \n") - - anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - t.Logf("Freight: %v", anyFreightID) - return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) - }) - - // test and uat push directly to their stage branches; prod is handled - // separately below because it is gated on a pull request merge. - for _, stage := range []string{"test", "uat"} { - feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - - t.Logf("Promoting %v to %v \n", stage, freightID) - - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - - if _, err := utils.PromoteAndWaitForPhase( - ctx, t, - project, stage, freightID, - kargoapi.PromotionPhaseSucceeded, - 10*time.Minute, - ); err != nil { - t.Fatal(err) - } - - _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) - - return ctx - }) - } - - feature.Assess("promote prod", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - creds := utils.RequireGitCreds(ctx, t) - stage := "prod" - - t.Logf("Promoting prod (merging its pull request) to %v \n", freightID) - - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - - if _, err := utils.PromoteWithPRMerge( - ctx, t, - project, stage, freightID, - creds.RepoURL, creds.Password, "open-pr", - 15*time.Minute, - ); err != nil { - t.Fatal(err) - } - - _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) - - return ctx - }) - - utils.TestEnv.Test(t, feature.Feature()) + utils.TestEnv.Test(t, feature()) } diff --git a/hack/test/e2e/suites/git_kustomize_image/feature.go b/hack/test/e2e/suites/git_kustomize_image/feature.go new file mode 100644 index 0000000000..f0158e2eb0 --- /dev/null +++ b/hack/test/e2e/suites/git_kustomize_image/feature.go @@ -0,0 +1,123 @@ +//nolint:forcetypeassert +package git_kustomize_image + +import ( + "context" + "embed" + "testing" + "time" + + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/hack/test/e2e/envfuncs" + "github.com/akuity/kargo/hack/test/e2e/framework/utils" +) + +func init() { + utils.TestFeatures = append(utils.TestFeatures, feature()) +} + +var ( + //go:embed testdata/* + TestData embed.FS +) + +func feature() features.Feature { + feature := features.New("git-kustomize-image") + + // This setup step is necessary to use this feature as a part of shared package test + // It sets the path to look up the fixtures files. + feature.Setup(utils.TestData(TestData)) + + project := "kargo-git-kustomize-image" + origin := "kargo-demo" + + feature.Setup(utils.SetupArgocdClient) + // Point the Argo CD ApplicationSet's source at the fork of the demo GitOps + // repository, mirroring the substitution applied to the Kargo fixtures. + feature.Setup(utils.SetupArgoCDFixturesWithRepoURL(project)) + feature.Teardown(utils.TeardownArgoCDFixtures) + + feature.Setup(utils.SetupKargoClients) + + // Setup and teardown fixtures from testdata folder. Substitute the git + // credentials Secret and the per-Stage gitRepo var with the fork and PAT + // from the test env. + feature.Setup(utils.RequireKargoCli) + feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { + creds := utils.RequireGitCreds(ctx, t) + return utils.NewSetupKargoFixtures( + utils.UpdateGitCredentialsSecret("manifests", creds.RepoURL, creds.Username, creds.Password), + utils.UpdateStagePromotionVar("", "gitRepo", creds.RepoURL), + )(ctx, t, cfg) + }) + feature.Teardown(utils.TeardownKargoFixtures) + + feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + t.Logf("Require freight \n") + + anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + t.Logf("Freight: %v", anyFreightID) + return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) + }) + + // test and uat push directly to their stage branches; prod is handled + // separately below because it is gated on a pull request merge. + for _, stage := range []string{"test", "uat"} { + feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + + t.Logf("Promoting %v to %v \n", stage, freightID) + + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + + if _, err := utils.PromoteAndWaitForPhase( + ctx, t, + project, stage, freightID, + kargoapi.PromotionPhaseSucceeded, + 10*time.Minute, + ); err != nil { + t.Fatal(err) + } + + _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) + + return ctx + }) + } + + feature.Assess("promote prod", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + creds := utils.RequireGitCreds(ctx, t) + stage := "prod" + + t.Logf("Promoting prod (merging its pull request) to %v \n", freightID) + + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + + if _, err := utils.PromoteWithPRMerge( + ctx, t, + project, stage, freightID, + creds.RepoURL, creds.Password, "open-pr", + 15*time.Minute, + ); err != nil { + t.Fatal(err) + } + + _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) + + return ctx + }) + + return feature.Feature() +} diff --git a/hack/test/e2e/suites/git_kustomize_image/git_kustomize_image_test.go b/hack/test/e2e/suites/git_kustomize_image/git_kustomize_image_test.go index 6cd55f9a0f..a6c69b486f 100644 --- a/hack/test/e2e/suites/git_kustomize_image/git_kustomize_image_test.go +++ b/hack/test/e2e/suites/git_kustomize_image/git_kustomize_image_test.go @@ -1,6 +1,6 @@ //go:build e2e //nolint:forcetypeassert -package git_kustomize_image_test +package git_kustomize_image // This test implements the Git driven, kustomize image-only example from // https://github.com/akuity/kargo-examples @@ -16,15 +16,8 @@ package git_kustomize_image_test // (see testdata/review/verification.yaml). import ( - "context" "testing" - "time" - "sigs.k8s.io/e2e-framework/pkg/envconf" - "sigs.k8s.io/e2e-framework/pkg/features" - - kargoapi "github.com/akuity/kargo/api/v1alpha1" - "github.com/akuity/kargo/hack/test/e2e/envfuncs" "github.com/akuity/kargo/hack/test/e2e/framework/utils" ) @@ -35,95 +28,5 @@ func TestMain(m *testing.M) { } func TestGitKustomizeImage(t *testing.T) { - feature := features.New("git-kustomize-image") - - project := "kargo-git-kustomize-image" - origin := "kargo-demo" - - feature.Setup(utils.SetupArgocdClient) - // Point the Argo CD ApplicationSet's source at the fork of the demo GitOps - // repository, mirroring the substitution applied to the Kargo fixtures. - feature.Setup(utils.SetupArgoCDFixturesWithRepoURL(project)) - feature.Teardown(utils.TeardownArgoCDFixtures) - - feature.Setup(utils.SetupKargoClients) - - // Setup and teardown fixtures from testdata folder. Substitute the git - // credentials Secret and the per-Stage gitRepo var with the fork and PAT - // from the test env. - feature.Setup(utils.RequireKargoCli) - feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { - creds := utils.RequireGitCreds(ctx, t) - return utils.NewSetupKargoFixtures( - utils.UpdateGitCredentialsSecret("manifests", creds.RepoURL, creds.Username, creds.Password), - utils.UpdateStagePromotionVar("", "gitRepo", creds.RepoURL), - )(ctx, t, cfg) - }) - feature.Teardown(utils.TeardownKargoFixtures) - - feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - t.Logf("Require freight \n") - - anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - t.Logf("Freight: %v", anyFreightID) - return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) - }) - - // test and uat push directly to their stage branches; prod is handled - // separately below because it is gated on a pull request merge. - for _, stage := range []string{"test", "uat"} { - feature.Assess("promote "+stage, func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - - t.Logf("Promoting %v to %v \n", stage, freightID) - - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - - if _, err := utils.PromoteAndWaitForPhase( - ctx, t, - project, stage, freightID, - kargoapi.PromotionPhaseSucceeded, - 10*time.Minute, - ); err != nil { - t.Fatal(err) - } - - _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) - - return ctx - }) - } - - feature.Assess("promote prod", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - creds := utils.RequireGitCreds(ctx, t) - stage := "prod" - - t.Logf("Promoting prod (merging its pull request) to %v \n", freightID) - - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - - if _, err := utils.PromoteWithPRMerge( - ctx, t, - project, stage, freightID, - creds.RepoURL, creds.Password, "open-pr", - 15*time.Minute, - ); err != nil { - t.Fatal(err) - } - - _ = utils.WaitForFreightToBeVerified(ctx, t, project, freightID, stage, 10*time.Minute) - - return ctx - }) - - utils.TestEnv.Test(t, feature.Feature()) + utils.TestEnv.Test(t, feature()) } diff --git a/hack/test/e2e/suites/http_promo_step/feature.go b/hack/test/e2e/suites/http_promo_step/feature.go new file mode 100644 index 0000000000..0e26915579 --- /dev/null +++ b/hack/test/e2e/suites/http_promo_step/feature.go @@ -0,0 +1,96 @@ +//nolint:forcetypeassert +package http_promo_step + +import ( + "context" + "embed" + "testing" + "time" + + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/hack/test/e2e/envfuncs" + "github.com/akuity/kargo/hack/test/e2e/framework/utils" +) + +func init() { + utils.TestFeatures = append(utils.TestFeatures, feature()) +} + +var ( + //go:embed testdata/* + TestData embed.FS +) + +func feature() features.Feature { + feature := features.New("http-promo-step") + + // This setup step is necessary to use this feature as a part of shared package test + // It sets the path to look up the fixtures files. + feature.Setup(utils.TestData(TestData)) + + project := "kargo-http-promo-step" + origin := "kargo-demo" + stage := "test" + + // Skip the tests if http_endpoint is not set + feature.Setup(utils.SkipIfNoEnvValue([]string{"context", "http_endpoint"})) + + feature.Setup(utils.SetupKargoClients) + + // Setup and teardown fixtures from testdata folder. Substitute the http + // endpoint the promotion posts to with the one configured in the test env. + feature.Setup(utils.RequireKargoCli) + feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { + endpointVal, err := envfuncs.GetEnv(ctx, []string{"context", "http_endpoint"}) + if err != nil { + t.Fatalf("cannot get context.http_endpoint from env; "+ + "configure it to an HTTP endpoint that returns 2xx to a POST: %v", err) + } + endpoint := endpointVal.(string) + + return utils.NewSetupKargoFixtures( + utils.UpdatePromotionTasksVar("promo-process", "url", endpoint), + )(ctx, t, cfg) + }) + feature.Teardown(utils.TeardownKargoFixtures) + + feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + t.Logf("Require freight \n") + + anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + t.Logf("Freight: %v", anyFreightID) + return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) + }) + + feature.Assess("http step posts to the configured endpoint", + func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + + t.Logf("Promoting %v to %v \n", stage, freightID) + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + + // The http step fails the promotion on a non-2xx response, so reaching + // Succeeded means the configured endpoint accepted the POST. + if _, err := utils.PromoteAndWaitForPhase( + ctx, t, + project, stage, freightID, + kargoapi.PromotionPhaseSucceeded, + 10*time.Minute, + ); err != nil { + t.Fatal(err) + } + + return ctx + }) + + return feature.Feature() +} diff --git a/hack/test/e2e/suites/http_promo_step/http_promo_step_test.go b/hack/test/e2e/suites/http_promo_step/http_promo_step_test.go index 67268449a1..b2d2ec651e 100644 --- a/hack/test/e2e/suites/http_promo_step/http_promo_step_test.go +++ b/hack/test/e2e/suites/http_promo_step/http_promo_step_test.go @@ -1,6 +1,6 @@ //go:build e2e //nolint:forcetypeassert -package http_promo_step_test +package http_promo_step // This test implements the http promotion step example from // https://github.com/akuity/kargo-examples (03-features/01-http-promo-step). @@ -15,15 +15,8 @@ package http_promo_step_test // single stage focused on the http step. import ( - "context" "testing" - "time" - "sigs.k8s.io/e2e-framework/pkg/envconf" - "sigs.k8s.io/e2e-framework/pkg/features" - - kargoapi "github.com/akuity/kargo/api/v1alpha1" - "github.com/akuity/kargo/hack/test/e2e/envfuncs" "github.com/akuity/kargo/hack/test/e2e/framework/utils" ) @@ -34,66 +27,5 @@ func TestMain(m *testing.M) { } func TestHTTPPromoStep(t *testing.T) { - feature := features.New("http-promo-step") - - project := "kargo-http-promo-step" - origin := "kargo-demo" - stage := "test" - - // Skip the tests if http_endpoint is not set - feature.Setup(utils.SkipIfNoEnvValue([]string{"context", "http_endpoint"})) - - feature.Setup(utils.SetupKargoClients) - - // Setup and teardown fixtures from testdata folder. Substitute the http - // endpoint the promotion posts to with the one configured in the test env. - feature.Setup(utils.RequireKargoCli) - feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { - endpointVal, err := envfuncs.GetEnv(ctx, []string{"context", "http_endpoint"}) - if err != nil { - t.Fatalf("cannot get context.http_endpoint from env; configure it to an HTTP endpoint that returns 2xx to a POST: %v", err) - } - endpoint := endpointVal.(string) - - return utils.NewSetupKargoFixtures( - utils.UpdatePromotionTasksVar("promo-process", "url", endpoint), - )(ctx, t, cfg) - }) - feature.Teardown(utils.TeardownKargoFixtures) - - feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - t.Logf("Require freight \n") - - anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - t.Logf("Freight: %v", anyFreightID) - return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) - }) - - feature.Assess("http step posts to the configured endpoint", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - - t.Logf("Promoting %v to %v \n", stage, freightID) - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - - // The http step fails the promotion on a non-2xx response, so reaching - // Succeeded means the configured endpoint accepted the POST. - if _, err := utils.PromoteAndWaitForPhase( - ctx, t, - project, stage, freightID, - kargoapi.PromotionPhaseSucceeded, - 10*time.Minute, - ); err != nil { - t.Fatal(err) - } - - return ctx - }) - - utils.TestEnv.Test(t, feature.Feature()) + utils.TestEnv.Test(t, feature()) } diff --git a/hack/test/e2e/suites/kargo_fixtures/feature.go b/hack/test/e2e/suites/kargo_fixtures/feature.go new file mode 100644 index 0000000000..bc7bee09a1 --- /dev/null +++ b/hack/test/e2e/suites/kargo_fixtures/feature.go @@ -0,0 +1,82 @@ +//nolint:forcetypeassert +package kargo_fixtures + +import ( + "context" + "embed" + "slices" + "testing" + + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" + + "github.com/akuity/kargo/hack/test/e2e/framework/utils" + "github.com/akuity/kargo/pkg/x/client/generated" +) + +func init() { + utils.TestFeatures = append(utils.TestFeatures, feature()) +} + +var ( + //go:embed testdata/* + TestData embed.FS +) + +func feature() features.Feature { + feature := features.New("Example kargo fixtures") + project := "kargo-fixtures" + + // This setup step is necessary to use this feature as a part of shared package test + // It sets the path to look up the fixtures files. + feature.Setup(utils.TestData(TestData)) + feature.Setup(utils.SetupKargoClients) + feature.Setup(utils.SetupKargoFixtures) + feature.Teardown(utils.TeardownKargoFixtures) + + feature.Assess("fixture project is created", + func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + kargoClient := ctx.Value(utils.KargoCLIKey).(generated.APIClient) + // FIXME: do we need to pass client.Options? + // FIXME: move this to helper functions package? + res, httpRes, err := kargoClient.CoreAPI.ListProjects(ctx).Execute() + if httpRes != nil { + _ = httpRes.Body.Close() + } + if err != nil { + t.Fatalf("list projects: %v", err) + } + projects := res.Items + index := slices.IndexFunc(projects, func(proj generated.Project) bool { + return *proj.Metadata.Name == project + }) + if index < 0 { + t.Fatalf("cannot find project `%s`", project) + } + return ctx + }) + + feature.Assess("fixture warehouse is created", + func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + kargoClient := ctx.Value(utils.KargoCLIKey).(generated.APIClient) + // FIXME: do we need to pass client.Options? + // FIXME: move this to helper functions package? + res, httpRes, err := kargoClient.CoreAPI.ListWarehouses(ctx, project).Execute() + if httpRes != nil { + _ = httpRes.Body.Close() + } + if err != nil { + t.Fatalf("list warehouses: %v", err) + } + warehouses := res.Items + index := slices.IndexFunc(warehouses, func(warehouse generated.Warehouse) bool { + return *warehouse.Metadata.Name == "images" + }) + if index < 0 { + t.Fatalf("cannot find warehouse `images`") + } + return ctx + }) + + return feature.Feature() +} diff --git a/hack/test/e2e/suites/kargo_fixtures/kargo_fixtures_test.go b/hack/test/e2e/suites/kargo_fixtures/kargo_fixtures_test.go index cc66d504a0..86a2171478 100644 --- a/hack/test/e2e/suites/kargo_fixtures/kargo_fixtures_test.go +++ b/hack/test/e2e/suites/kargo_fixtures/kargo_fixtures_test.go @@ -1,20 +1,15 @@ //go:build e2e && examples + //nolint:forcetypeassert -package kargo_example +package kargo_fixtures // This test shows an example of using YAML files to define Kargo fixtures to use in tests. // It sets up fixtures and verifies that they exist. import ( - "context" - "slices" "testing" - "sigs.k8s.io/e2e-framework/pkg/envconf" - "sigs.k8s.io/e2e-framework/pkg/features" - "github.com/akuity/kargo/hack/test/e2e/framework/utils" - "github.com/akuity/kargo/pkg/x/client/generated" ) // This file provides necessary setup for a test package to run environment setup for e2e test. @@ -24,56 +19,5 @@ func TestMain(m *testing.M) { } func TestKargoFixtures(t *testing.T) { - feature := features.New("Example kargo fixtures") - project := "kargo-fixtures" - - feature.Setup(utils.SetupKargoClients) - feature.Setup(utils.SetupKargoFixtures) - feature.Teardown(utils.TeardownKargoFixtures) - - feature.Assess("fixture project is created", - func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - kargoClient := ctx.Value(utils.KargoCLIKey).(generated.APIClient) - // FIXME: do we need to pass client.Options? - // FIXME: move this to helper functions package? - res, httpRes, err := kargoClient.CoreAPI.ListProjects(ctx).Execute() - if httpRes != nil { - _ = httpRes.Body.Close() - } - if err != nil { - t.Fatalf("list projects: %v", err) - } - projects := res.Items - index := slices.IndexFunc(projects, func(proj generated.Project) bool { - return *proj.Metadata.Name == project - }) - if index < 0 { - t.Fatalf("cannot find project `%s`", project) - } - return ctx - }) - - feature.Assess("fixture warehouse is created", - func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - kargoClient := ctx.Value(utils.KargoCLIKey).(generated.APIClient) - // FIXME: do we need to pass client.Options? - // FIXME: move this to helper functions package? - res, httpRes, err := kargoClient.CoreAPI.ListWarehouses(ctx, project).Execute() - if httpRes != nil { - _ = httpRes.Body.Close() - } - if err != nil { - t.Fatalf("list warehouses: %v", err) - } - warehouses := res.Items - index := slices.IndexFunc(warehouses, func(warehouse generated.Warehouse) bool { - return *warehouse.Metadata.Name == "images" - }) - if index < 0 { - t.Fatalf("cannot find warehouse `images`") - } - return ctx - }) - - utils.TestEnv.Test(t, feature.Feature()) + utils.TestEnv.Test(t, feature()) } diff --git a/hack/test/e2e/suites/kargo_promotion_fail/feature.go b/hack/test/e2e/suites/kargo_promotion_fail/feature.go new file mode 100644 index 0000000000..fdb039954d --- /dev/null +++ b/hack/test/e2e/suites/kargo_promotion_fail/feature.go @@ -0,0 +1,59 @@ +//nolint:forcetypeassert +package kargo_promotion_fail + +import ( + "context" + "embed" + "testing" + "time" + + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/hack/test/e2e/framework/utils" +) + +func init() { + utils.TestFeatures = append(utils.TestFeatures, feature()) +} + +var ( + //go:embed testdata/* + TestData embed.FS +) + +func feature() features.Feature { + feature := features.New("Example kargo promotion") + // This setup step is necessary to use this feature as a part of shared package test + // It sets the path to look up the fixtures files. + feature.Setup(utils.TestData(TestData)) + project := "kargo-promotion-fail" + // Setup and teardown fixtures from testdata folder + feature.Setup(utils.SetupKargoClients) + feature.Setup(utils.SetupKargoFixtures) + feature.Teardown(utils.TeardownKargoFixtures) + + feature.Assess("promotion fails", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + stage := "kargo-promotion-fail-stage" + origin := "images" + + anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 5*time.Minute) + if err != nil { + t.Fatal(err) + } + + _, err = utils.PromoteAndWaitForPhase( + ctx, t, + project, stage, anyFreightID, + kargoapi.PromotionPhaseFailed, + 5*time.Minute) + if err != nil { + t.Fatal(err) + } + + return ctx + }) + + return feature.Feature() +} diff --git a/hack/test/e2e/suites/kargo_promotion_fail/kargo_promotion_fail_test.go b/hack/test/e2e/suites/kargo_promotion_fail/kargo_promotion_fail_test.go index 8114468c9d..771f55d446 100644 --- a/hack/test/e2e/suites/kargo_promotion_fail/kargo_promotion_fail_test.go +++ b/hack/test/e2e/suites/kargo_promotion_fail/kargo_promotion_fail_test.go @@ -1,19 +1,13 @@ //go:build e2e //nolint:forcetypeassert -package kargo_promotion_fail_test +package kargo_promotion_fail // This test shows an example of running Kargo promotion with stage defined in YAML fixtures. // Specifically it executes the `fail` stage and checks that promotion fails. import ( - "context" "testing" - "time" - "sigs.k8s.io/e2e-framework/pkg/envconf" - "sigs.k8s.io/e2e-framework/pkg/features" - - kargoapi "github.com/akuity/kargo/api/v1alpha1" "github.com/akuity/kargo/hack/test/e2e/framework/utils" ) @@ -24,34 +18,5 @@ func TestMain(m *testing.M) { } func TestKargoPromotionFail(t *testing.T) { - feature := features.New("Example kargo promotion") - project := "kargo-promotion-fail" - // Setup and teardown fixtures from testdata folder - feature.Setup(utils.SetupKargoClients) - feature.Setup(utils.SetupKargoFixtures) - feature.Teardown(utils.TeardownKargoFixtures) - - feature.Assess("promotion fails", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - stage := "kargo-promotion-fail-stage" - origin := "images" - - anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 5*time.Minute) - if err != nil { - t.Fatal(err) - } - - _, err = utils.PromoteAndWaitForPhase( - ctx, t, - project, stage, anyFreightID, - kargoapi.PromotionPhaseFailed, - 5*time.Minute) - if err != nil { - t.Fatal(err) - } - - return ctx - }) - - utils.TestEnv.Test(t, feature.Feature()) - + utils.TestEnv.Test(t, feature()) } diff --git a/hack/test/e2e/suites/shared/shared_test.go b/hack/test/e2e/suites/shared/shared_test.go new file mode 100644 index 0000000000..64fb3d9f65 --- /dev/null +++ b/hack/test/e2e/suites/shared/shared_test.go @@ -0,0 +1,45 @@ +//go:build e2e && shared + +//nolint:forcetypeassert +package shared_test + +// This suite runs all test features registered in utils.TestFeatures +// This is useful to share multiple suites in the same kind cluster (for performance) +// Suites need to be imported in order to run as a part of shared test + +import ( + "testing" + + "github.com/akuity/kargo/hack/test/e2e/framework/utils" + _ "github.com/akuity/kargo/hack/test/e2e/suites/argocd_helm_chart" + _ "github.com/akuity/kargo/hack/test/e2e/suites/kargo_fixtures" + + _ "github.com/akuity/kargo/hack/test/e2e/suites/argocd_helm_chart" + _ "github.com/akuity/kargo/hack/test/e2e/suites/argocd_helm_chart_n_image" + _ "github.com/akuity/kargo/hack/test/e2e/suites/argocd_helm_commit_n_image" + _ "github.com/akuity/kargo/hack/test/e2e/suites/argocd_helm_image_chart_repo" + _ "github.com/akuity/kargo/hack/test/e2e/suites/argocd_helm_image_git_repo" + _ "github.com/akuity/kargo/hack/test/e2e/suites/argocd_kustomize_commit_n_image" + _ "github.com/akuity/kargo/hack/test/e2e/suites/argocd_kustomize_image" + _ "github.com/akuity/kargo/hack/test/e2e/suites/argocd_update" + _ "github.com/akuity/kargo/hack/test/e2e/suites/argocd_wait" + _ "github.com/akuity/kargo/hack/test/e2e/suites/git_commit_only" + _ "github.com/akuity/kargo/hack/test/e2e/suites/git_helm_commit_n_image" + _ "github.com/akuity/kargo/hack/test/e2e/suites/git_helm_image" + _ "github.com/akuity/kargo/hack/test/e2e/suites/git_kustomize_commit_n_image" + _ "github.com/akuity/kargo/hack/test/e2e/suites/git_kustomize_image" + // _ "github.com/akuity/kargo/hack/test/e2e/suites/http_promo_step" + _ "github.com/akuity/kargo/hack/test/e2e/suites/kargo_fixtures" + _ "github.com/akuity/kargo/hack/test/e2e/suites/kargo_promotion_fail" + _ "github.com/akuity/kargo/hack/test/e2e/suites/soak_time" + _ "github.com/akuity/kargo/hack/test/e2e/suites/vars" + _ "github.com/akuity/kargo/hack/test/e2e/suites/yaml_parse_update" +) + +func TestMain(m *testing.M) { + utils.InitEnv(m) +} + +func TestAll(t *testing.T) { + utils.TestEnv.TestInParallel(t, utils.TestFeatures...) +} diff --git a/hack/test/e2e/suites/soak_time/feature.go b/hack/test/e2e/suites/soak_time/feature.go new file mode 100644 index 0000000000..88a8bd5418 --- /dev/null +++ b/hack/test/e2e/suites/soak_time/feature.go @@ -0,0 +1,127 @@ +//nolint:forcetypeassert +package soak_time + +import ( + "context" + "embed" + "net/http" + "testing" + "time" + + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/hack/test/e2e/envfuncs" + "github.com/akuity/kargo/hack/test/e2e/framework/utils" +) + +func init() { + utils.TestFeatures = append(utils.TestFeatures, feature()) +} + +var ( + //go:embed testdata/* + TestData embed.FS +) + +// soakTime must match the requiredSoakTime configured on the uat Stage in +// testdata/kargo/kargo.yaml. +const soakTime = 2 * time.Minute + +func feature() features.Feature { + feature := features.New("soak-time") + + // This setup step is necessary to use this feature as a part of shared package test + // It sets the path to look up the fixtures files. + feature.Setup(utils.TestData(TestData)) + + project := "kargo-soak-time" + origin := "kargo-demo" + + feature.Setup(utils.SetupKargoClients) + + // Setup and teardown fixtures from testdata folder. + feature.Setup(utils.RequireKargoCli) + feature.Setup(utils.SetupKargoFixtures) + feature.Teardown(utils.TeardownKargoFixtures) + + feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + t.Logf("Require freight \n") + + anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + t.Logf("Freight: %v", anyFreightID) + return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) + }) + + feature.Assess("uat only accepts freight after soak time", + func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + + // Record the soak clock start before the freight enters test: the + // freight becomes "currently in" test no earlier than this, so uat + // cannot become eligible before soakStart + soakTime. + soakStart := time.Now() + + t.Logf("Promoting test to %v \n", freightID) + if err := utils.RefreshStage(ctx, t, project, "test"); err != nil { + t.Fatal(err) + } + if _, err := utils.PromoteAndWaitForPhase( + ctx, t, + project, "test", freightID, + kargoapi.PromotionPhaseSucceeded, + 10*time.Minute, + ); err != nil { + t.Fatal(err) + } + utils.WaitForFreightToBeVerified(ctx, t, project, freightID, "test", 10*time.Minute) + + // The freight is now verified in test but has not soaked long enough, + // so uat must reject a promotion attempt with 400 Bad Request. + if err := utils.RefreshStage(ctx, t, project, "uat"); err != nil { + t.Fatal(err) + } + status, err := utils.TryPromoteToStage(ctx, project, "uat", freightID) + if err == nil || status != http.StatusBadRequest { + t.Fatalf( + "expected uat to reject freight before soak time with 400, got status %d, err %v", + status, err) + } + if elapsed := time.Since(soakStart); elapsed >= soakTime { + t.Fatalf( + "soak time %v already elapsed (%v) before the rejection check; test is inconclusive", + soakTime, + elapsed) + } + t.Logf("uat correctly rejected freight before soak time (status %d)", status) + + // Promote to uat. StartPromotion retries the 400 until the freight has + // soaked, so this call blocks until the soak time elapses and succeeds. + t.Logf("Promoting uat (waiting out the %v soak time) \n", soakTime) + if _, err := utils.PromoteAndWaitForPhase( + ctx, t, + project, "uat", freightID, + kargoapi.PromotionPhaseSucceeded, + soakTime+5*time.Minute, + ); err != nil { + t.Fatal(err) + } + + if elapsed := time.Since(soakStart); elapsed < soakTime { + t.Fatalf("uat promotion succeeded after %v, before the required soak time of %v", elapsed, soakTime) + } else { + t.Logf("uat promotion succeeded after %v (>= soak time %v)", elapsed, soakTime) + } + + utils.WaitForFreightToBeVerified(ctx, t, project, freightID, "uat", 10*time.Minute) + + return ctx + }) + + return feature.Feature() +} diff --git a/hack/test/e2e/suites/soak_time/soak_time_test.go b/hack/test/e2e/suites/soak_time/soak_time_test.go index ecda75eceb..f6fa22a049 100644 --- a/hack/test/e2e/suites/soak_time/soak_time_test.go +++ b/hack/test/e2e/suites/soak_time/soak_time_test.go @@ -1,6 +1,6 @@ //go:build e2e //nolint:forcetypeassert -package soak_time_test +package soak_time // This test implements the soak-time example from // https://github.com/akuity/kargo-examples (03-features/02-soak-time). Freight @@ -13,23 +13,11 @@ package soak_time_test // AnalysisTemplate verification is stripped (see testdata/review/verification.yaml). import ( - "context" - "net/http" "testing" - "time" - "sigs.k8s.io/e2e-framework/pkg/envconf" - "sigs.k8s.io/e2e-framework/pkg/features" - - kargoapi "github.com/akuity/kargo/api/v1alpha1" - "github.com/akuity/kargo/hack/test/e2e/envfuncs" "github.com/akuity/kargo/hack/test/e2e/framework/utils" ) -// soakTime must match the requiredSoakTime configured on the uat Stage in -// testdata/kargo/kargo.yaml. -const soakTime = 2 * time.Minute - // This file provides necessary setup for a test package to run environment setup for e2e test. // Because golang doesn't allow import of test code, this code needs to be added to each test package. func TestMain(m *testing.M) { @@ -37,90 +25,5 @@ func TestMain(m *testing.M) { } func TestSoakTime(t *testing.T) { - feature := features.New("soak-time") - - project := "kargo-soak-time" - origin := "kargo-demo" - - feature.Setup(utils.SetupKargoClients) - - // Setup and teardown fixtures from testdata folder. - feature.Setup(utils.RequireKargoCli) - feature.Setup(utils.SetupKargoFixtures) - feature.Teardown(utils.TeardownKargoFixtures) - - feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - t.Logf("Require freight \n") - - anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - t.Logf("Freight: %v", anyFreightID) - return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) - }) - - feature.Assess("uat only accepts freight after soak time", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - - // Record the soak clock start before the freight enters test: the - // freight becomes "currently in" test no earlier than this, so uat - // cannot become eligible before soakStart + soakTime. - soakStart := time.Now() - - t.Logf("Promoting test to %v \n", freightID) - if err := utils.RefreshStage(ctx, t, project, "test"); err != nil { - t.Fatal(err) - } - if _, err := utils.PromoteAndWaitForPhase( - ctx, t, - project, "test", freightID, - kargoapi.PromotionPhaseSucceeded, - 10*time.Minute, - ); err != nil { - t.Fatal(err) - } - utils.WaitForFreightToBeVerified(ctx, t, project, freightID, "test", 10*time.Minute) - - // The freight is now verified in test but has not soaked long enough, - // so uat must reject a promotion attempt with 400 Bad Request. - if err := utils.RefreshStage(ctx, t, project, "uat"); err != nil { - t.Fatal(err) - } - status, err := utils.TryPromoteToStage(ctx, project, "uat", freightID) - if err == nil || status != http.StatusBadRequest { - t.Fatalf( - "expected uat to reject freight before soak time with 400, got status %d, err %v", - status, err) - } - if elapsed := time.Since(soakStart); elapsed >= soakTime { - t.Fatalf("soak time %v already elapsed (%v) before the rejection check; test is inconclusive", soakTime, elapsed) - } - t.Logf("uat correctly rejected freight before soak time (status %d)", status) - - // Promote to uat. StartPromotion retries the 400 until the freight has - // soaked, so this call blocks until the soak time elapses and succeeds. - t.Logf("Promoting uat (waiting out the %v soak time) \n", soakTime) - if _, err := utils.PromoteAndWaitForPhase( - ctx, t, - project, "uat", freightID, - kargoapi.PromotionPhaseSucceeded, - soakTime+5*time.Minute, - ); err != nil { - t.Fatal(err) - } - - if elapsed := time.Since(soakStart); elapsed < soakTime { - t.Fatalf("uat promotion succeeded after %v, before the required soak time of %v", elapsed, soakTime) - } else { - t.Logf("uat promotion succeeded after %v (>= soak time %v)", elapsed, soakTime) - } - - utils.WaitForFreightToBeVerified(ctx, t, project, freightID, "uat", 10*time.Minute) - - return ctx - }) - - utils.TestEnv.Test(t, feature.Feature()) + utils.TestEnv.Test(t, feature()) } diff --git a/hack/test/e2e/suites/vars/feature.go b/hack/test/e2e/suites/vars/feature.go new file mode 100644 index 0000000000..f204349284 --- /dev/null +++ b/hack/test/e2e/suites/vars/feature.go @@ -0,0 +1,110 @@ +//nolint:forcetypeassert +package vars + +import ( + "context" + "embed" + "testing" + "time" + + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/hack/test/e2e/envfuncs" + "github.com/akuity/kargo/hack/test/e2e/framework/utils" +) + +func init() { + utils.TestFeatures = append(utils.TestFeatures, feature()) +} + +var ( + //go:embed testdata/* + TestData embed.FS +) + +func feature() features.Feature { + feature := features.New("vars") + + project := "kargo-vars" + origin := "vars" + stage := "vars" + + // This setup step is necessary to use this feature as a part of shared package test + // It sets the path to look up the fixtures files. + feature.Setup(utils.TestData(TestData)) + feature.Setup(utils.SetupKargoClients) + + // The chart Warehouse and pokeapi are public, so no substitution is needed. + feature.Setup(utils.RequireKargoCli) + feature.Setup(utils.SetupKargoFixtures) + feature.Teardown(utils.TeardownKargoFixtures) + + feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + t.Logf("Require freight \n") + + anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + t.Logf("Freight: %v", anyFreightID) + return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) + }) + + feature.Assess("vars resolve at every level", + func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + + t.Logf("Promoting %v to %v \n", stage, freightID) + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + promotion, err := utils.PromoteAndWaitForPhase( + ctx, t, + project, stage, freightID, + kargoapi.PromotionPhaseSucceeded, + 10*time.Minute, + ) + if err != nil { + t.Fatal(err) + } + + // key -> (var level, expected pokemon name) + expected := []struct { + key string + level string + value string + }{ + {"pokemon1", "Stage spec.vars", "pikachu"}, + {"pokemon2", "Stage promotionTemplate.spec.vars", "charmander"}, + {"pokemon3", "Stage promotionTemplate.spec.steps[].vars", "bulbasaur"}, + {"pokemon4", "PromotionTask spec.vars", "ditto"}, + } + for _, e := range expected { + got, ok := utils.PromotionStepOutput(promotion, "output", e.key) + if !ok { + t.Fatalf( + "promotion output is missing %q (%s); state: %v", + e.key, e.level, promotion.Status.GetState()) + } + if got != e.value { + t.Fatalf("var at %s resolved to %q, want %q", e.level, got, e.value) + } + t.Logf("var at %s resolved to %q", e.level, got) + } + + return ctx + }) + + feature.Assess("stage is verified", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + // The AnalysisTemplate argument is populated from vars.pokemon_1, the + // fifth var level; a successful verification confirms it resolved. + utils.WaitForStageVerified(ctx, t, project, stage, 10*time.Minute) + t.Logf("stage %q verified successfully", stage) + return ctx + }) + + return feature.Feature() +} diff --git a/hack/test/e2e/suites/vars/testdata/kargo/kargo.yaml b/hack/test/e2e/suites/vars/testdata/kargo/kargo.yaml index 3a598f7f26..8da3894f20 100644 --- a/hack/test/e2e/suites/vars/testdata/kargo/kargo.yaml +++ b/hack/test/e2e/suites/vars/testdata/kargo/kargo.yaml @@ -11,8 +11,8 @@ metadata: spec: subscriptions: - chart: - repoURL: https://charts.bitnami.com/bitnami - name: nginx + repoURL: https://grafana-community.github.io/helm-charts + name: grafana --- apiVersion: kargo.akuity.io/v1alpha1 kind: PromotionTask diff --git a/hack/test/e2e/suites/vars/vars_test.go b/hack/test/e2e/suites/vars/vars_test.go index a3e4fdab0e..410d73f3e7 100644 --- a/hack/test/e2e/suites/vars/vars_test.go +++ b/hack/test/e2e/suites/vars/vars_test.go @@ -1,6 +1,6 @@ //go:build e2e //nolint:forcetypeassert -package vars_test +package vars // This test implements the vars example from // https://github.com/akuity/kargo-examples (03-features/04-vars). It exercises @@ -18,15 +18,8 @@ package vars_test // (parameterized by vars.pokemon_1) to succeed. import ( - "context" "testing" - "time" - "sigs.k8s.io/e2e-framework/pkg/envconf" - "sigs.k8s.io/e2e-framework/pkg/features" - - kargoapi "github.com/akuity/kargo/api/v1alpha1" - "github.com/akuity/kargo/hack/test/e2e/envfuncs" "github.com/akuity/kargo/hack/test/e2e/framework/utils" ) @@ -37,80 +30,5 @@ func TestMain(m *testing.M) { } func TestVars(t *testing.T) { - feature := features.New("vars") - - project := "kargo-vars" - origin := "vars" - stage := "vars" - - feature.Setup(utils.SetupKargoClients) - - // The chart Warehouse and pokeapi are public, so no substitution is needed. - feature.Setup(utils.RequireKargoCli) - feature.Setup(utils.SetupKargoFixtures) - feature.Teardown(utils.TeardownKargoFixtures) - - feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - t.Logf("Require freight \n") - - anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - t.Logf("Freight: %v", anyFreightID) - return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) - }) - - feature.Assess("vars resolve at every level", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - - t.Logf("Promoting %v to %v \n", stage, freightID) - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - promotion, err := utils.PromoteAndWaitForPhase( - ctx, t, - project, stage, freightID, - kargoapi.PromotionPhaseSucceeded, - 10*time.Minute, - ) - if err != nil { - t.Fatal(err) - } - - // key -> (var level, expected pokemon name) - expected := []struct { - key string - level string - value string - }{ - {"pokemon1", "Stage spec.vars", "pikachu"}, - {"pokemon2", "Stage promotionTemplate.spec.vars", "charmander"}, - {"pokemon3", "Stage promotionTemplate.spec.steps[].vars", "bulbasaur"}, - {"pokemon4", "PromotionTask spec.vars", "ditto"}, - } - for _, e := range expected { - got, ok := utils.PromotionStepOutput(promotion, "output", e.key) - if !ok { - t.Fatalf("promotion output is missing %q (%s); state: %v", e.key, e.level, promotion.Status.GetState()) - } - if got != e.value { - t.Fatalf("var at %s resolved to %q, want %q", e.level, got, e.value) - } - t.Logf("var at %s resolved to %q", e.level, got) - } - - return ctx - }) - - feature.Assess("stage is verified", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - // The AnalysisTemplate argument is populated from vars.pokemon_1, the - // fifth var level; a successful verification confirms it resolved. - utils.WaitForStageVerified(ctx, t, project, stage, 10*time.Minute) - t.Logf("stage %q verified successfully", stage) - return ctx - }) - - utils.TestEnv.Test(t, feature.Feature()) + utils.TestEnv.Test(t, feature()) } diff --git a/hack/test/e2e/suites/yaml_parse_update/feature.go b/hack/test/e2e/suites/yaml_parse_update/feature.go new file mode 100644 index 0000000000..2ec85e1433 --- /dev/null +++ b/hack/test/e2e/suites/yaml_parse_update/feature.go @@ -0,0 +1,117 @@ +//nolint:forcetypeassert +package yaml_parse_update + +import ( + "context" + "embed" + "testing" + "time" + + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/hack/test/e2e/envfuncs" + "github.com/akuity/kargo/hack/test/e2e/framework/utils" +) + +func init() { + utils.TestFeatures = append(utils.TestFeatures, feature()) +} + +var ( + //go:embed testdata/* + TestData embed.FS +) + +func feature() features.Feature { + feature := features.New("yaml-parse-update") + + feature.Setup(utils.TestData(TestData)) + + project := "kargo-yaml-parse-update" + origin := "kargo-demo" + stage := "yaml-parse-update" + + feature.Setup(utils.SetupKargoClients) + + // Setup and teardown fixtures from testdata folder. The demo repo is public, + // so no credentials are needed; only the repo URL is substituted with the + // fork from the test env (Warehouse subscription and the promotion var). + feature.Setup(utils.RequireKargoCli) + feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { + kargoDemoRepoVal, err := envfuncs.GetEnv(ctx, []string{"context", "kargo_demo_gitops_repo"}) + if err != nil { + t.Fatalf("cannot get kargo_demo_gitops_repo %v", err) + } + kargoDemoRepo := kargoDemoRepoVal.(string) + + return utils.NewSetupKargoFixtures( + utils.UpdateWarehouseGitRepoURL("kargo-demo", kargoDemoRepo), + utils.UpdateStagePromotionVar("", "repoURL", kargoDemoRepo), + )(ctx, t, cfg) + }) + feature.Teardown(utils.TeardownKargoFixtures) + + feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + t.Logf("Require freight \n") + + anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) + if err != nil { + t.Fatal(err) + } + + t.Logf("Freight: %v", anyFreightID) + return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) + }) + + feature.Assess("yaml-update updates the parsed field", + func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { + freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) + + t.Logf("Promoting %v to %v \n", stage, freightID) + if err := utils.RefreshStage(ctx, t, project, stage); err != nil { + t.Fatal(err) + } + promotion, err := utils.PromoteAndWaitForPhase( + ctx, t, + project, stage, freightID, + kargoapi.PromotionPhaseSucceeded, + 10*time.Minute, + ) + if err != nil { + t.Fatal(err) + } + + original, ok := utils.PromotionStepOutput(promotion, "output", "originalImage") + if !ok { + t.Fatalf("promotion output %q is missing originalImage; state: %v", + "output", promotion.Status.GetState()) + } + updated, ok := utils.PromotionStepOutput(promotion, "output", "updatedImage") + if !ok { + t.Fatalf("promotion output %q is missing updatedImage; state: %v", + "output", promotion.Status.GetState()) + } + expected, ok := utils.PromotionStepOutput(promotion, "output", "expectedImage") + if !ok { + t.Fatalf("promotion output %q is missing expectedImage; state: %v", + "output", promotion.Status.GetState()) + } + + // yaml-update must have written the new value, which the second + // yaml-parse then read back. + if updated != expected { + t.Fatalf("yaml-update did not update the field: got image.name %q, want %q", updated, expected) + } + // The field must have actually changed from its original value. + if updated == original { + t.Fatalf("yaml-update left the field unchanged at %q", original) + } + + t.Logf("yaml-update changed image.name from %q to %q", original, updated) + return ctx + }) + + return feature.Feature() +} diff --git a/hack/test/e2e/suites/yaml_parse_update/yaml_parse_update_test.go b/hack/test/e2e/suites/yaml_parse_update/yaml_parse_update_test.go index ee293b9a52..05fb4e3b90 100644 --- a/hack/test/e2e/suites/yaml_parse_update/yaml_parse_update_test.go +++ b/hack/test/e2e/suites/yaml_parse_update/yaml_parse_update_test.go @@ -1,6 +1,6 @@ //go:build e2e //nolint:forcetypeassert -package yaml_parse_update_test +package yaml_parse_update // This test is adapted from the yaml-parse / yaml-update example at // https://github.com/akuity/kargo-examples (03-features/03-yaml-parse-update). @@ -15,15 +15,8 @@ package yaml_parse_update_test // that yaml-update actually changed it. import ( - "context" "testing" - "time" - "sigs.k8s.io/e2e-framework/pkg/envconf" - "sigs.k8s.io/e2e-framework/pkg/features" - - kargoapi "github.com/akuity/kargo/api/v1alpha1" - "github.com/akuity/kargo/hack/test/e2e/envfuncs" "github.com/akuity/kargo/hack/test/e2e/framework/utils" ) @@ -34,87 +27,5 @@ func TestMain(m *testing.M) { } func TestYAMLParseUpdate(t *testing.T) { - feature := features.New("yaml-parse-update") - - project := "kargo-yaml-parse-update" - origin := "kargo-demo" - stage := "yaml-parse-update" - - feature.Setup(utils.SetupKargoClients) - - // Setup and teardown fixtures from testdata folder. The demo repo is public, - // so no credentials are needed; only the repo URL is substituted with the - // fork from the test env (Warehouse subscription and the promotion var). - feature.Setup(utils.RequireKargoCli) - feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { - kargoDemoRepoVal, err := envfuncs.GetEnv(ctx, []string{"context", "kargo_demo_gitops_repo"}) - if err != nil { - t.Fatalf("cannot get kargo_demo_gitops_repo %v", err) - } - kargoDemoRepo := kargoDemoRepoVal.(string) - - return utils.NewSetupKargoFixtures( - utils.UpdateWarehouseGitRepoURL("kargo-demo", kargoDemoRepo), - utils.UpdateStagePromotionVar("", "repoURL", kargoDemoRepo), - )(ctx, t, cfg) - }) - feature.Teardown(utils.TeardownKargoFixtures) - - feature.Assess("require freight", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - t.Logf("Require freight \n") - - anyFreightID, err := utils.WaitForLatestFreight(ctx, project, origin, 10*time.Minute) - if err != nil { - t.Fatal(err) - } - - t.Logf("Freight: %v", anyFreightID) - return context.WithValue(ctx, envfuncs.ContextKey("freight_id"), anyFreightID) - }) - - feature.Assess("yaml-update updates the parsed field", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context { - freightID := ctx.Value(envfuncs.ContextKey("freight_id")).(string) - - t.Logf("Promoting %v to %v \n", stage, freightID) - if err := utils.RefreshStage(ctx, t, project, stage); err != nil { - t.Fatal(err) - } - promotion, err := utils.PromoteAndWaitForPhase( - ctx, t, - project, stage, freightID, - kargoapi.PromotionPhaseSucceeded, - 10*time.Minute, - ) - if err != nil { - t.Fatal(err) - } - - original, ok := utils.PromotionStepOutput(promotion, "output", "originalImage") - if !ok { - t.Fatalf("promotion output %q is missing originalImage; state: %v", "output", promotion.Status.GetState()) - } - updated, ok := utils.PromotionStepOutput(promotion, "output", "updatedImage") - if !ok { - t.Fatalf("promotion output %q is missing updatedImage; state: %v", "output", promotion.Status.GetState()) - } - expected, ok := utils.PromotionStepOutput(promotion, "output", "expectedImage") - if !ok { - t.Fatalf("promotion output %q is missing expectedImage; state: %v", "output", promotion.Status.GetState()) - } - - // yaml-update must have written the new value, which the second - // yaml-parse then read back. - if updated != expected { - t.Fatalf("yaml-update did not update the field: got image.name %q, want %q", updated, expected) - } - // The field must have actually changed from its original value. - if updated == original { - t.Fatalf("yaml-update left the field unchanged at %q", original) - } - - t.Logf("yaml-update changed image.name from %q to %q", original, updated) - return ctx - }) - - utils.TestEnv.Test(t, feature.Feature()) + utils.TestEnv.Test(t, feature()) } diff --git a/hack/test/e2e/values.test.yaml b/hack/test/e2e/values.test.yaml index 578f961437..9c7bf03b9a 100644 --- a/hack/test/e2e/values.test.yaml +++ b/hack/test/e2e/values.test.yaml @@ -1,3 +1,6 @@ +image: + repository: docker.io/library/kargo + tag: dev global: clusterSecretsNamespace: kargo-cluster-secrets api: