Skip to content

Commit dfa0f72

Browse files
authored
feat: add support for validate option when provisioning/maintaining argocd applications (#411)
Signed-off-by: Jiacheng Xu <[email protected]>
1 parent 8b48c7c commit dfa0f72

File tree

3 files changed

+74
-20
lines changed

3 files changed

+74
-20
lines changed

argocd/resource_argocd_application.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ func resourceArgoCDApplication() *schema.Resource {
4343
Optional: true,
4444
Default: true,
4545
},
46+
"validate": {
47+
Type: schema.TypeBool,
48+
Description: "Whether to validate the application spec before creating or updating the application.",
49+
Optional: true,
50+
Default: true,
51+
},
4652
"status": applicationStatusSchema(),
4753
},
4854
SchemaVersion: 4,
@@ -132,6 +138,7 @@ func resourceArgoCDApplicationCreate(ctx context.Context, d *schema.ResourceData
132138
return featureNotSupported(features.ManagedNamespaceMetadata)
133139
}
134140

141+
validate := d.Get("validate").(bool)
135142
app, err := si.ApplicationClient.Create(ctx, &applicationClient.ApplicationCreateRequest{
136143
Application: &application.Application{
137144
ObjectMeta: objectMeta,
@@ -141,7 +148,9 @@ func resourceArgoCDApplicationCreate(ctx context.Context, d *schema.ResourceData
141148
APIVersion: "argoproj.io/v1alpha1",
142149
},
143150
},
151+
Validate: &validate,
144152
})
153+
145154
if err != nil {
146155
return argoCDAPIError("create", "application", objectMeta.Name, err)
147156
} else if app == nil {
@@ -296,6 +305,7 @@ func resourceArgoCDApplicationUpdate(ctx context.Context, d *schema.ResourceData
296305
}
297306
}
298307

308+
validate := d.Get("validate").(bool)
299309
if _, err = si.ApplicationClient.Update(ctx, &applicationClient.ApplicationUpdateRequest{
300310
Application: &application.Application{
301311
ObjectMeta: objectMeta,
@@ -305,6 +315,7 @@ func resourceArgoCDApplicationUpdate(ctx context.Context, d *schema.ResourceData
305315
APIVersion: "argoproj.io/v1alpha1",
306316
},
307317
},
318+
Validate: &validate,
308319
}); err != nil {
309320
return argoCDAPIError("update", "application", objectMeta.Name, err)
310321
}

argocd/resource_argocd_application_test.go

Lines changed: 62 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func TestAccArgoCDApplication(t *testing.T) {
4040
ResourceName: "argocd_application." + name,
4141
ImportState: true,
4242
ImportStateVerify: true,
43-
ImportStateVerifyIgnore: []string{"wait", "cascade", "metadata.0.generation", "metadata.0.resource_version", "status"},
43+
ImportStateVerifyIgnore: []string{"wait", "cascade", "metadata.0.generation", "metadata.0.resource_version", "status", "validate"},
4444
},
4545
{
4646
// Update
@@ -87,7 +87,7 @@ func TestAccArgoCDApplication(t *testing.T) {
8787
ResourceName: "argocd_application." + name,
8888
ImportState: true,
8989
ImportStateVerify: true,
90-
ImportStateVerifyIgnore: []string{"wait", "cascade", "metadata.0.generation", "metadata.0.resource_version"},
90+
ImportStateVerifyIgnore: []string{"wait", "cascade", "metadata.0.generation", "metadata.0.resource_version", "validate"},
9191
},
9292
},
9393
})
@@ -149,7 +149,7 @@ ingress:
149149
ResourceName: "argocd_application.helm",
150150
ImportState: true,
151151
ImportStateVerify: true,
152-
ImportStateVerifyIgnore: []string{"wait", "cascade", "metadata.0.generation", "metadata.0.resource_version", "status"},
152+
ImportStateVerifyIgnore: []string{"wait", "cascade", "metadata.0.generation", "metadata.0.resource_version", "status", "validate"},
153153
},
154154
},
155155
})
@@ -176,7 +176,10 @@ func TestAccArgoCDApplication_Kustomize(t *testing.T) {
176176
Steps: []resource.TestStep{
177177
{
178178
Config: testAccArgoCDApplicationKustomize(
179-
acctest.RandomWithPrefix("test-acc")),
179+
acctest.RandomWithPrefix("test-acc"),
180+
"examples/helloWorld",
181+
true,
182+
),
180183
Check: resource.ComposeTestCheckFunc(
181184
resource.TestCheckResourceAttrSet(
182185
"argocd_application.kustomize",
@@ -198,7 +201,7 @@ func TestAccArgoCDApplication_Kustomize(t *testing.T) {
198201
ResourceName: "argocd_application.kustomize",
199202
ImportState: true,
200203
ImportStateVerify: true,
201-
ImportStateVerifyIgnore: []string{"wait", "cascade", "metadata.0.generation", "metadata.0.resource_version", "status"},
204+
ImportStateVerifyIgnore: []string{"wait", "cascade", "metadata.0.generation", "metadata.0.resource_version", "status", "validate"},
202205
},
203206
},
204207
})
@@ -233,7 +236,7 @@ func TestAccArgoCDApplication_IgnoreDifferences(t *testing.T) {
233236
ResourceName: "argocd_application.ignore_differences",
234237
ImportState: true,
235238
ImportStateVerify: true,
236-
ImportStateVerifyIgnore: []string{"wait", "cascade", "status"},
239+
ImportStateVerifyIgnore: []string{"wait", "cascade", "status", "validate"},
237240
},
238241
{
239242
Config: testAccArgoCDApplicationIgnoreDiffJQPathExpressions(
@@ -259,7 +262,7 @@ func TestAccArgoCDApplication_IgnoreDifferences(t *testing.T) {
259262
ResourceName: "argocd_application.ignore_differences_jqpe",
260263
ImportState: true,
261264
ImportStateVerify: true,
262-
ImportStateVerifyIgnore: []string{"wait", "cascade", "status"},
265+
ImportStateVerifyIgnore: []string{"wait", "cascade", "status", "validate"},
263266
},
264267
},
265268
})
@@ -293,7 +296,7 @@ func TestAccArgoCDApplication_RevisionHistoryLimit(t *testing.T) {
293296
ResourceName: "argocd_application.revision_history_limit",
294297
ImportState: true,
295298
ImportStateVerify: true,
296-
ImportStateVerifyIgnore: []string{"wait", "cascade", "status"},
299+
ImportStateVerifyIgnore: []string{"wait", "cascade", "status", "validate"},
297300
},
298301
},
299302
})
@@ -322,7 +325,7 @@ func TestAccArgoCDApplication_OptionalDestinationNamespace(t *testing.T) {
322325
ResourceName: "argocd_application.no_namespace",
323326
ImportState: true,
324327
ImportStateVerify: true,
325-
ImportStateVerifyIgnore: []string{"wait", "cascade", "status"},
328+
ImportStateVerifyIgnore: []string{"wait", "cascade", "status", "validate"},
326329
},
327330
},
328331
})
@@ -407,7 +410,7 @@ func TestAccArgoCDApplication_DirectoryJsonnet(t *testing.T) {
407410
ResourceName: "argocd_application.directory",
408411
ImportState: true,
409412
ImportStateVerify: true,
410-
ImportStateVerifyIgnore: []string{"wait", "cascade", "metadata.0.generation", "metadata.0.resource_version", "status"},
413+
ImportStateVerifyIgnore: []string{"wait", "cascade", "metadata.0.generation", "metadata.0.resource_version", "status", "validate"},
411414
},
412415
},
413416
})
@@ -513,7 +516,7 @@ func TestAccArgoCDApplication_EmptyDirectory(t *testing.T) {
513516
ResourceName: "argocd_application.directory",
514517
ImportState: true,
515518
ImportStateVerify: true,
516-
ImportStateVerifyIgnore: []string{"wait", "cascade", "metadata.0.generation", "metadata.0.resource_version", "status"},
519+
ImportStateVerifyIgnore: []string{"wait", "cascade", "metadata.0.generation", "metadata.0.resource_version", "status", "validate"},
517520
},
518521
},
519522
})
@@ -545,7 +548,7 @@ func TestAccArgoCDApplication_DirectoryIncludeExclude(t *testing.T) {
545548
ResourceName: "argocd_application.directory",
546549
ImportState: true,
547550
ImportStateVerify: true,
548-
ImportStateVerifyIgnore: []string{"wait", "cascade", "metadata.0.generation", "metadata.0.resource_version", "status"},
551+
ImportStateVerifyIgnore: []string{"wait", "cascade", "metadata.0.generation", "metadata.0.resource_version", "status", "validate"},
549552
},
550553
},
551554
})
@@ -605,7 +608,7 @@ func TestAccArgoCDApplication_SyncPolicy(t *testing.T) {
605608
ResourceName: "argocd_application.sync_policy",
606609
ImportState: true,
607610
ImportStateVerify: true,
608-
ImportStateVerifyIgnore: []string{"wait", "cascade", "metadata.0.generation", "metadata.0.resource_version", "status"},
611+
ImportStateVerifyIgnore: []string{"wait", "cascade", "metadata.0.generation", "metadata.0.resource_version", "status", "validate"},
609612
},
610613
},
611614
})
@@ -957,7 +960,7 @@ func TestAccArgoCDApplication_CustomNamespace(t *testing.T) {
957960
ResourceName: "argocd_application.custom_namespace",
958961
ImportState: true,
959962
ImportStateVerify: true,
960-
ImportStateVerifyIgnore: []string{"wait", "cascade", "status"},
963+
ImportStateVerifyIgnore: []string{"wait", "cascade", "status", "validate"},
961964
},
962965
},
963966
})
@@ -991,7 +994,7 @@ func TestAccArgoCDApplication_MultipleSources(t *testing.T) {
991994
ResourceName: "argocd_application.multiple_sources",
992995
ImportState: true,
993996
ImportStateVerify: true,
994-
ImportStateVerifyIgnore: []string{"wait", "cascade", "metadata.0.generation", "metadata.0.resource_version", "status"},
997+
ImportStateVerifyIgnore: []string{"wait", "cascade", "metadata.0.generation", "metadata.0.resource_version", "status", "validate"},
995998
},
996999
},
9971000
})
@@ -1029,7 +1032,7 @@ func TestAccArgoCDApplication_HelmValuesFromExternalGitRepo(t *testing.T) {
10291032
ResourceName: "argocd_application.helm_values_external",
10301033
ImportState: true,
10311034
ImportStateVerify: true,
1032-
ImportStateVerifyIgnore: []string{"wait", "cascade", "metadata.0.generation", "metadata.0.resource_version", "status"},
1035+
ImportStateVerifyIgnore: []string{"wait", "cascade", "metadata.0.generation", "metadata.0.resource_version", "status", "validate"},
10331036
},
10341037
},
10351038
})
@@ -1052,7 +1055,7 @@ func TestAccArgoCDApplication_ManagedNamespaceMetadata(t *testing.T) {
10521055
ResourceName: "argocd_application.namespace_metadata",
10531056
ImportState: true,
10541057
ImportStateVerify: true,
1055-
ImportStateVerifyIgnore: []string{"wait", "cascade", "metadata.0.generation", "metadata.0.resource_version"},
1058+
ImportStateVerifyIgnore: []string{"wait", "cascade", "metadata.0.generation", "metadata.0.resource_version", "validate"},
10561059
},
10571060
},
10581061
})
@@ -1085,6 +1088,42 @@ func TestAccArgoCDApplication_Wait(t *testing.T) {
10851088
})
10861089
}
10871090

1091+
func TestAccArgoCDApplication_Validate(t *testing.T) {
1092+
resource.ParallelTest(t, resource.TestCase{
1093+
PreCheck: func() { testAccPreCheck(t) },
1094+
ProviderFactories: testAccProviders,
1095+
Steps: []resource.TestStep{
1096+
{
1097+
Config: testAccArgoCDApplicationKustomize(
1098+
acctest.RandomWithPrefix("test-acc"),
1099+
"path-does-not-exist",
1100+
true,
1101+
),
1102+
ExpectError: regexp.MustCompile("app path does not exist"),
1103+
},
1104+
{
1105+
Config: testAccArgoCDApplicationKustomize(
1106+
acctest.RandomWithPrefix("test-acc"),
1107+
"path-does-not-exist",
1108+
false,
1109+
),
1110+
Check: resource.ComposeTestCheckFunc(
1111+
resource.TestCheckResourceAttr(
1112+
"argocd_application.kustomize",
1113+
"validate",
1114+
"false",
1115+
),
1116+
resource.TestCheckResourceAttr(
1117+
"argocd_application.kustomize",
1118+
"spec.0.source.0.path",
1119+
"path-does-not-exist",
1120+
),
1121+
),
1122+
},
1123+
},
1124+
})
1125+
}
1126+
10881127
func testAccArgoCDApplicationSimple(name, targetRevision string, wait bool) string {
10891128
return fmt.Sprintf(`
10901129
resource "argocd_application" "%[1]s" {
@@ -1219,7 +1258,7 @@ resource "argocd_application" "helm_file_parameters" {
12191258
}`, name)
12201259
}
12211260

1222-
func testAccArgoCDApplicationKustomize(name string) string {
1261+
func testAccArgoCDApplicationKustomize(name string, path string, validate bool) string {
12231262
return fmt.Sprintf(`
12241263
resource "argocd_application" "kustomize" {
12251264
metadata {
@@ -1233,7 +1272,7 @@ resource "argocd_application" "kustomize" {
12331272
spec {
12341273
source {
12351274
repo_url = "https://github.com/kubernetes-sigs/kustomize"
1236-
path = "examples/helloWorld"
1275+
path = "%s"
12371276
target_revision = "release-kustomize-v3.7"
12381277
kustomize {
12391278
name_prefix = "foo-"
@@ -1257,8 +1296,11 @@ resource "argocd_application" "kustomize" {
12571296
namespace = "default"
12581297
}
12591298
}
1299+
1300+
validate = %t
1301+
12601302
}
1261-
`, name)
1303+
`, name, path, validate)
12621304
}
12631305

12641306
func testAccArgoCDApplicationDirectoryNoPath(name string) string {

docs/resources/application.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ resource "argocd_application" "multiple_sources" {
177177

178178
- `cascade` (Boolean) Whether to applying cascading deletion when application is removed.
179179
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
180+
- `validate` (Boolean) Whether to validate the application spec before creating or updating the application.
180181
- `wait` (Boolean) Upon application creation or update, wait for application health/sync status to be healthy/Synced, upon application deletion, wait for application to be removed, when set to true. Wait timeouts are controlled by Terraform Create, Update and Delete resource timeouts (all default to 5 minutes). **Note**: if ArgoCD decides not to sync an application (e.g. because the project to which the application belongs has a `sync_window` applied) then you will experience an expected timeout event if `wait = true`.
181182

182183
### Read-Only

0 commit comments

Comments
 (0)