From a038606945838e1e85374204840bb5bece891827 Mon Sep 17 00:00:00 2001 From: OneMatchFox <878612+onematchfox@users.noreply.github.com> Date: Thu, 4 May 2023 16:00:45 +0200 Subject: [PATCH 1/3] build: drop tests for `2.4.x` series and add `2.7.1` --- .github/workflows/tests.yml | 2 +- GNUmakefile | 2 +- scripts/testacc_prepare_env.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1e04a20e..8374035e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -48,7 +48,7 @@ jobs: strategy: fail-fast: false matrix: - argocd_version: ["v2.4.0", "v2.4.28", "v2.5.0", "v2.5.16", "v2.6.0", "v2.6.7"] + argocd_version: ["v2.5.0", "v2.5.16", "v2.6.0", "v2.6.7", "v2.7.1"] steps: - name: Check out code uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 diff --git a/GNUmakefile b/GNUmakefile index f9a43a24..9eecf879 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -5,7 +5,7 @@ ARGOCD_SERVER?=127.0.0.1:8080 ARGOCD_AUTH_USERNAME?=admin ARGOCD_AUTH_PASSWORD?=acceptancetesting ARGOCD_CONTEXT?=kind-argocd -ARGOCD_VERSION?=v2.6.7 +ARGOCD_VERSION?=v2.7.1 export diff --git a/scripts/testacc_prepare_env.sh b/scripts/testacc_prepare_env.sh index f1cf950d..9c36450c 100755 --- a/scripts/testacc_prepare_env.sh +++ b/scripts/testacc_prepare_env.sh @@ -3,7 +3,7 @@ export PATH=$PATH:. -argocd_version=${ARGOCD_VERSION:-v2.6.7} +argocd_version=${ARGOCD_VERSION:-v2.7.1} k8s_version=${ARGOCD_KUBERNETES_VERSION:-v1.24.7} echo "\n--- Kustomize sanity checks\n" From 477d2aa0af72aee2d5c648f99e6cfbc70de1fa4a Mon Sep 17 00:00:00 2001 From: OneMatchFox <878612+onematchfox@users.noreply.github.com> Date: Thu, 4 May 2023 16:56:10 +0200 Subject: [PATCH 2/3] fix(application): fix use of `List` to read applications on ArgoCD `2.7`+ --- argocd/resource_argocd_application.go | 60 +++++++++++++++++---------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/argocd/resource_argocd_application.go b/argocd/resource_argocd_application.go index b6381eb5..a1b7c234 100644 --- a/argocd/resource_argocd_application.go +++ b/argocd/resource_argocd_application.go @@ -98,29 +98,33 @@ func resourceArgoCDApplicationCreate(ctx context.Context, d *schema.ResourceData return []diag.Diagnostic{ { Severity: diag.Error, - Summary: fmt.Sprintf("application %s could not be created", objectMeta.Name), + Summary: fmt.Sprintf("failed to get application %s", objectMeta.Name), Detail: err.Error(), }, } } if apps != nil { - if len(apps.Items) != 1 { + l := len(apps.Items) + + switch { + case l < 1: + break + case l == 1: + switch apps.Items[0].DeletionTimestamp { + case nil: + default: + // Pre-existing app is still in Kubernetes soft deletion queue + time.Sleep(time.Duration(*apps.Items[0].DeletionGracePeriodSeconds)) + } + case l > 1: return []diag.Diagnostic{ { Severity: diag.Error, Summary: fmt.Sprintf("found multiple applications matching name '%s' and namespace '%s'", objectMeta.Name, objectMeta.Namespace), - Detail: err.Error(), }, } } - - switch apps.Items[0].DeletionTimestamp { - case nil: - default: - // Pre-existing app is still in Kubernetes soft deletion queue - time.Sleep(time.Duration(*apps.Items[0].DeletionGracePeriodSeconds)) - } } featureApplicationLevelSyncOptionsSupported, err := si.isFeatureSupported(featureApplicationLevelSyncOptions) @@ -271,7 +275,7 @@ func resourceArgoCDApplicationCreate(ctx context.Context, d *schema.ResourceData } if len(list.Items) != 1 { - return resource.NonRetryableError(fmt.Errorf("found multiple applications matching name '%s' and namespace '%s'", app.Name, app.Namespace)) + return resource.NonRetryableError(fmt.Errorf("found unexpected number of applications matching name '%s' and namespace '%s'. Items: %d", app.Name, app.Namespace, len(list.Items))) } if list.Items[0].Status.Health.Status != health.HealthStatusHealthy { @@ -326,18 +330,25 @@ func resourceArgoCDApplicationRead(ctx context.Context, d *schema.ResourceData, return []diag.Diagnostic{ { Severity: diag.Error, - Summary: fmt.Sprintf("application %s not found", appName), + Summary: fmt.Sprintf("failed to get application %s", appName), Detail: err.Error(), }, } } - if len(apps.Items) != 1 { + l := len(apps.Items) + + switch { + case l < 1: + d.SetId("") + return diag.Diagnostics{} + case l == 1: + break + case l > 1: return []diag.Diagnostic{ { Severity: diag.Error, Summary: fmt.Sprintf("found multiple applications matching name '%s' and namespace '%s'", appName, namespace), - Detail: err.Error(), }, } } @@ -506,7 +517,7 @@ func resourceArgoCDApplicationUpdate(ctx context.Context, d *schema.ResourceData // appRequest.ResourceVersion = app.ResourceVersion // } - if len(apps.Items) != 1 { + if len(apps.Items) > 1 { return []diag.Diagnostic{ { Severity: diag.Error, @@ -543,7 +554,7 @@ func resourceArgoCDApplicationUpdate(ctx context.Context, d *schema.ResourceData } if len(list.Items) != 1 { - return resource.NonRetryableError(fmt.Errorf("found multiple applications matching name '%s' and namespace '%s'", *appQuery.Name, *appQuery.AppNamespace)) + return resource.NonRetryableError(fmt.Errorf("found unexpected number of applications matching name '%s' and namespace '%s'. Items: %d", *appQuery.Name, *appQuery.AppNamespace, len(list.Items))) } if list.Items[0].Status.ReconciledAt.Equal(apps.Items[0].Status.ReconciledAt) { @@ -606,17 +617,20 @@ func resourceArgoCDApplicationDelete(ctx context.Context, d *schema.ResourceData if wait, ok := d.GetOk("wait"); ok && wait.(bool) { if err := resource.RetryContext(ctx, d.Timeout(schema.TimeoutDelete), func() *resource.RetryError { - _, err := si.ApplicationClient.List(ctx, &applicationClient.ApplicationQuery{ + apps, err := si.ApplicationClient.List(ctx, &applicationClient.ApplicationQuery{ Name: &appName, AppNamespace: &namespace, }) - if err == nil { - return resource.RetryableError(fmt.Errorf("application %s is still present", appName)) - } - - if !strings.Contains(err.Error(), "NotFound") { - return resource.NonRetryableError(err) + switch err { + case nil: + if apps != nil && len(apps.Items) > 0 { + return resource.RetryableError(fmt.Errorf("application %s is still present", appName)) + } + default: + if !strings.Contains(err.Error(), "NotFound") { + return resource.NonRetryableError(err) + } } d.SetId("") From fc856ebad6838bc51fb028fa71a200c065cca69c Mon Sep 17 00:00:00 2001 From: OneMatchFox <878612+onematchfox@users.noreply.github.com> Date: Thu, 4 May 2023 18:06:53 +0200 Subject: [PATCH 3/3] tests: ensure resources in parallel tests have unique names --- argocd/resource_argocd_application_test.go | 83 +++++++++++----------- argocd/resource_argocd_repository_test.go | 83 ++++++++++++---------- 2 files changed, 88 insertions(+), 78 deletions(-) diff --git a/argocd/resource_argocd_application_test.go b/argocd/resource_argocd_application_test.go index 7d009bd9..1d3c5109 100644 --- a/argocd/resource_argocd_application_test.go +++ b/argocd/resource_argocd_application_test.go @@ -13,42 +13,42 @@ import ( ) func TestAccArgoCDApplication(t *testing.T) { - commonName := acctest.RandomWithPrefix("test-acc") + name := acctest.RandomWithPrefix("test-acc") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, ProviderFactories: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccArgoCDApplicationSimple(commonName, "8.0.0", false), + Config: testAccArgoCDApplicationSimple(name, "8.0.0", false), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet( - "argocd_application.simple", + "argocd_application."+name, "metadata.0.uid", ), resource.TestCheckResourceAttr( - "argocd_application.simple", + "argocd_application."+name, "spec.0.source.0.target_revision", "8.0.0", ), ), }, { - ResourceName: "argocd_application.simple", + ResourceName: "argocd_application." + name, ImportState: true, ImportStateVerify: true, ImportStateVerifyIgnore: []string{"wait", "cascade", "metadata.0.generation", "metadata.0.resource_version"}, }, { // Update - Config: testAccArgoCDApplicationSimple(commonName, "9.0.0", false), + Config: testAccArgoCDApplicationSimple(name, "9.0.0", false), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet( - "argocd_application.simple", + "argocd_application."+name, "metadata.0.uid", ), resource.TestCheckResourceAttr( - "argocd_application.simple", + "argocd_application."+name, "spec.0.source.0.target_revision", "9.0.0", ), @@ -56,15 +56,15 @@ func TestAccArgoCDApplication(t *testing.T) { }, { // Update with wait = true - Config: testAccArgoCDApplicationSimple(commonName, "9.4.1", true), + Config: testAccArgoCDApplicationSimple(name, "9.4.1", true), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr( - "argocd_application.simple", + "argocd_application."+name, "wait", "true", ), resource.TestCheckResourceAttr( - "argocd_application.simple", + "argocd_application."+name, "spec.0.source.0.target_revision", "9.4.1", ), @@ -266,18 +266,18 @@ func TestAccArgoCDApplication_OptionalDestinationNamespace(t *testing.T) { Config: testAccArgoCDApplication_OptionalDestinationNamespace(acctest.RandomWithPrefix("test-acc")), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet( - "argocd_application.simple", + "argocd_application.no_namespace", "metadata.0.uid", ), resource.TestCheckResourceAttr( - "argocd_application.simple", + "argocd_application.no_namespace", "spec.0.destination.0.namespace", "", // optional strings are maintained in state as blank strings ), ), }, { - ResourceName: "argocd_application.simple", + ResourceName: "argocd_application.no_namespace", ImportState: true, ImportStateVerify: true, ImportStateVerifyIgnore: []string{"wait", "cascade"}, @@ -578,15 +578,15 @@ func TestAccArgoCDApplication_NoSyncPolicyBlock(t *testing.T) { Config: testAccArgoCDApplicationNoSyncPolicy(acctest.RandomWithPrefix("test-acc")), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet( - "argocd_application.simple", + "argocd_application.no_sync_policy", "metadata.0.uid", ), resource.TestCheckNoResourceAttr( - "argocd_application.simple", + "argocd_application.no_sync_policy", "spec.0.sync_policy.0.retry.0.backoff.0.duration", ), resource.TestCheckNoResourceAttr( - "argocd_application.simple", + "argocd_application.no_sync_policy", "spec.0.sync_policy.0.automated.0.prune", ), ), @@ -604,15 +604,15 @@ func TestAccArgoCDApplication_EmptySyncPolicyBlock(t *testing.T) { Config: testAccArgoCDApplicationEmptySyncPolicy(acctest.RandomWithPrefix("test-acc")), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet( - "argocd_application.simple", + "argocd_application.empty_sync_policy", "metadata.0.uid", ), resource.TestCheckNoResourceAttr( - "argocd_application.simple", + "argocd_application.empty_sync_policy", "spec.0.sync_policy.0.retry.0.backoff.0.duration", ), resource.TestCheckNoResourceAttr( - "argocd_application.simple", + "argocd_application.empty_sync_policy", "spec.0.sync_policy.0.automated.0.prune", ), ), @@ -630,15 +630,15 @@ func TestAccArgoCDApplication_NoAutomatedBlock(t *testing.T) { Config: testAccArgoCDApplicationNoAutomated(acctest.RandomWithPrefix("test-acc")), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet( - "argocd_application.simple", + "argocd_application.no_automated", "metadata.0.uid", ), resource.TestCheckResourceAttrSet( - "argocd_application.simple", + "argocd_application.no_automated", "spec.0.sync_policy.0.retry.0.backoff.0.duration", ), resource.TestCheckNoResourceAttr( - "argocd_application.simple", + "argocd_application.no_automated", "spec.0.sync_policy.0.automated.0.prune", ), ), @@ -656,15 +656,15 @@ func TestAccArgoCDApplication_EmptyAutomatedBlock(t *testing.T) { Config: testAccArgoCDApplicationEmptyAutomated(acctest.RandomWithPrefix("test-acc")), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet( - "argocd_application.simple", + "argocd_application.empty_automated", "metadata.0.uid", ), resource.TestCheckResourceAttrSet( - "argocd_application.simple", + "argocd_application.empty_automated", "spec.0.sync_policy.0.automated.#", ), resource.TestCheckNoResourceAttr( - "argocd_application.simple", + "argocd_application.empty_automated", "spec.0.sync_policy.0.automated.0.prune", ), ), @@ -967,7 +967,7 @@ func TestAccArgoCDApplication_SkipCrds(t *testing.T) { } func TestAccArgoCDApplication_CustomNamespace(t *testing.T) { - name := acctest.RandomWithPrefix("test-acc-custom-namespace") + name := acctest.RandomWithPrefix("test-acc") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckFeatureSupported(t, featureProjectSourceNamespaces) }, @@ -977,13 +977,13 @@ func TestAccArgoCDApplication_CustomNamespace(t *testing.T) { Config: testAccArgoCDApplicationCustomNamespace(name), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet( - "argocd_application.simple", + "argocd_application.custom_namespace", "metadata.0.uid", ), ), }, { - ResourceName: "argocd_application.simple", + ResourceName: "argocd_application.custom_namespace", ImportState: true, ImportStateVerify: true, ImportStateVerifyIgnore: []string{"wait", "cascade"}, @@ -1028,21 +1028,22 @@ func TestAccArgoCDApplication_MultipleSources(t *testing.T) { func TestAccArgoCDApplication_Wait(t *testing.T) { chartRevision := "9.4.1" + name := acctest.RandomWithPrefix("test-acc") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, ProviderFactories: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccArgoCDApplicationSimple(acctest.RandomWithPrefix("test-acc"), chartRevision, true), + Config: testAccArgoCDApplicationSimple(name, chartRevision, true), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr( - "argocd_application.simple", + "argocd_application."+name, "wait", "true", ), resource.TestCheckResourceAttr( - "argocd_application.simple", + "argocd_application."+name, "spec.0.source.0.target_revision", chartRevision, ), @@ -1054,7 +1055,7 @@ func TestAccArgoCDApplication_Wait(t *testing.T) { func testAccArgoCDApplicationSimple(name, targetRevision string, wait bool) string { return fmt.Sprintf(` -resource "argocd_application" "simple" { +resource "argocd_application" "%[1]s" { metadata { name = "%[1]s" namespace = "argocd" @@ -1561,7 +1562,7 @@ resource "argocd_application" "ignore_differences_jqpe" { func testAccArgoCDApplication_OptionalDestinationNamespace(name string) string { return fmt.Sprintf(` -resource "argocd_application" "simple" { +resource "argocd_application" "no_namespace" { metadata { name = "%s" namespace = "argocd" @@ -1585,7 +1586,7 @@ resource "argocd_application" "simple" { func testAccArgoCDApplicationNoSyncPolicy(name string) string { return fmt.Sprintf(` -resource "argocd_application" "simple" { +resource "argocd_application" "no_sync_policy" { metadata { name = "%s" namespace = "argocd" @@ -1610,7 +1611,7 @@ resource "argocd_application" "simple" { func testAccArgoCDApplicationEmptySyncPolicy(name string) string { return fmt.Sprintf(` -resource "argocd_application" "simple" { +resource "argocd_application" "empty_sync_policy" { metadata { name = "%s" namespace = "argocd" @@ -1637,7 +1638,7 @@ resource "argocd_application" "simple" { func testAccArgoCDApplicationNoAutomated(name string) string { return fmt.Sprintf(` -resource "argocd_application" "simple" { +resource "argocd_application" "no_automated" { metadata { name = "%s" namespace = "argocd" @@ -1672,7 +1673,7 @@ resource "argocd_application" "simple" { func testAccArgoCDApplicationEmptyAutomated(name string) string { return fmt.Sprintf(` -resource "argocd_application" "simple" { +resource "argocd_application" "empty_automated" { metadata { name = "%s" namespace = "argocd" @@ -1964,7 +1965,7 @@ resource "argocd_application" "crds" { func testAccArgoCDApplicationCustomNamespace(name string) string { return fmt.Sprintf(` -resource "argocd_project" "simple" { +resource "argocd_project" "custom_namespace" { metadata { name = "%[1]s" namespace = "argocd" @@ -1982,14 +1983,14 @@ resource "argocd_project" "simple" { } } -resource "argocd_application" "simple" { +resource "argocd_application" "custom_namespace" { metadata { name = "%[1]s" namespace = "mynamespace-1" } spec { - project = argocd_project.simple.metadata[0].name + project = argocd_project.custom_namespace.metadata[0].name source { repo_url = "https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami" chart = "redis" diff --git a/argocd/resource_argocd_repository_test.go b/argocd/resource_argocd_repository_test.go index 240ceb3a..ccb0e0d8 100644 --- a/argocd/resource_argocd_repository_test.go +++ b/argocd/resource_argocd_repository_test.go @@ -11,7 +11,7 @@ import ( "github.com/stretchr/testify/assert" ) -func TestAccArgoCDRepository(t *testing.T) { +func TestAccArgoCDRepository_Simple(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, ProviderFactories: testAccProviders, @@ -29,6 +29,24 @@ func TestAccArgoCDRepository(t *testing.T) { ImportState: true, ImportStateVerify: true, }, + { + Config: testAccArgoCDRepositoryPublicUsageInApplication(acctest.RandString(10)), + Check: resource.TestCheckResourceAttrSet( + "argocd_application.public", + "metadata.0.uid", + ), + }, + }, + }) +} + +func TestAccArgoCDRepository_Helm(t *testing.T) { + projectName := acctest.RandString(10) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: testAccProviders, + Steps: []resource.TestStep{ { Config: testAccArgoCDRepositoryHelm(), Check: resource.TestCheckResourceAttr( @@ -43,29 +61,46 @@ func TestAccArgoCDRepository(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccArgoCDRepositoryPublicUsageInApplication(acctest.RandString(10)), - Check: resource.TestCheckResourceAttrSet( - "argocd_application.public", - "metadata.0.uid", + Config: testAccArgoCDRepositoryHelmProjectScoped(projectName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "argocd_repository.helm", + "connection_state_status", + "Successful", + ), + resource.TestCheckResourceAttr( + "argocd_repository.helm", + "project", + projectName, + ), ), }, + }, + }) +} + +func TestAccArgoCDRepository_PrivateSSH(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: testAccProviders, + Steps: []resource.TestStep{ { Config: testAccArgoCDRepositoryPrivateGitSSH("git@private-git-repository.argocd.svc.cluster.local:~/project-1.git"), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr( - "argocd_repository.private", + "argocd_repository.private_ssh", "connection_state_status", "Successful", ), resource.TestCheckResourceAttr( - "argocd_repository.private", + "argocd_repository.private_ssh", "inherited_creds", "false", ), ), }, { - ResourceName: "argocd_repository.private", + ResourceName: "argocd_repository.private_ssh", ImportState: true, ImportStateVerify: true, ImportStateVerifyIgnore: []string{"ssh_private_key"}, @@ -73,7 +108,7 @@ func TestAccArgoCDRepository(t *testing.T) { { Config: testAccArgoCDRepositoryMultiplePrivateGitSSH(10), Check: testCheckMultipleResourceAttr( - "argocd_repository.private", + "argocd_repository.private_ssh", "connection_state_status", "Successful", 10, @@ -83,32 +118,6 @@ func TestAccArgoCDRepository(t *testing.T) { }) } -func TestAccArgoCDRepositoryScoped(t *testing.T) { - projectName := acctest.RandString(10) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t); testAccPreCheckFeatureSupported(t, featureProjectScopedRepositories) }, - ProviderFactories: testAccProviders, - Steps: []resource.TestStep{ - { - Config: testAccArgoCDRepositoryHelmProjectScoped(projectName), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr( - "argocd_repository.helm", - "connection_state_status", - "Successful", - ), - resource.TestCheckResourceAttr( - "argocd_repository.helm", - "project", - projectName, - ), - ), - }, - }, - }) -} - func TestAccArgoCDRepositoryScoped_NotSupported_On_OlderVersions(t *testing.T) { name := acctest.RandomWithPrefix("test-acc-scoped-repo") @@ -246,7 +255,7 @@ resource "argocd_application" "public" { func testAccArgoCDRepositoryPrivateGitSSH(repoUrl string) string { return fmt.Sprintf(` -resource "argocd_repository" "private" { +resource "argocd_repository" "private_ssh" { repo = "%s" type = "git" insecure = true @@ -257,7 +266,7 @@ resource "argocd_repository" "private" { func testAccArgoCDRepositoryMultiplePrivateGitSSH(repoCount int) string { return fmt.Sprintf(` -resource "argocd_repository" "private" { +resource "argocd_repository" "private_ssh" { count = %d repo = format("git@private-git-repository.argocd.svc.cluster.local:~/project-%%d.git", count.index+1) type = "git"