Skip to content

Commit 79342b9

Browse files
authored
fix: crash when using argocd_application.spec.info (#168)
1 parent 1d7b81d commit 79342b9

File tree

2 files changed

+303
-10
lines changed

2 files changed

+303
-10
lines changed

argocd/resource_argocd_application_test.go

Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package argocd
33
import (
44
"context"
55
"fmt"
6+
"regexp"
67
"strconv"
78
"testing"
89

@@ -502,6 +503,121 @@ func TestAccArgoCDApplication_OptionalPath(t *testing.T) {
502503
}})
503504
}
504505

506+
func TestAccArgoCDApplication_Info(t *testing.T) {
507+
name := acctest.RandomWithPrefix("test-acc-info")
508+
info := acctest.RandString(8)
509+
value := acctest.RandString(8)
510+
511+
resource.ParallelTest(t, resource.TestCase{
512+
PreCheck: func() { testAccPreCheck(t) },
513+
ProviderFactories: testAccProviders,
514+
Steps: []resource.TestStep{
515+
{
516+
Config: testAccArgoCDApplicationInfo(name, info, value),
517+
Check: resource.ComposeTestCheckFunc(
518+
resource.TestCheckResourceAttrSet(
519+
"argocd_application.info",
520+
"metadata.0.uid",
521+
),
522+
resource.TestCheckResourceAttr(
523+
"argocd_application.info",
524+
"spec.0.info.0.name",
525+
info,
526+
),
527+
resource.TestCheckResourceAttr(
528+
"argocd_application.info",
529+
"spec.0.info.0.value",
530+
value,
531+
),
532+
),
533+
},
534+
{
535+
Config: testAccArgoCDApplicationInfoNoName(name, value),
536+
Check: resource.ComposeTestCheckFunc(
537+
resource.TestCheckResourceAttrSet(
538+
"argocd_application.info",
539+
"metadata.0.uid",
540+
),
541+
resource.TestCheckResourceAttr(
542+
"argocd_application.info",
543+
"spec.0.info.0.name",
544+
"",
545+
),
546+
resource.TestCheckResourceAttr(
547+
"argocd_application.info",
548+
"spec.0.info.0.value",
549+
value,
550+
),
551+
),
552+
},
553+
{
554+
Config: testAccArgoCDApplicationInfoNoValue(name, info),
555+
Check: resource.ComposeTestCheckFunc(
556+
resource.TestCheckResourceAttrSet(
557+
"argocd_application.info",
558+
"metadata.0.uid",
559+
),
560+
resource.TestCheckResourceAttr(
561+
"argocd_application.info",
562+
"spec.0.info.0.name",
563+
info,
564+
),
565+
resource.TestCheckResourceAttr(
566+
"argocd_application.info",
567+
"spec.0.info.0.value",
568+
"",
569+
),
570+
),
571+
},
572+
{
573+
Config: testAccArgoCDApplicationInfo(name, info, value),
574+
Check: resource.ComposeTestCheckFunc(
575+
resource.TestCheckResourceAttrSet(
576+
"argocd_application.info",
577+
"metadata.0.uid",
578+
),
579+
resource.TestCheckResourceAttr(
580+
"argocd_application.info",
581+
"spec.0.info.0.name",
582+
info,
583+
),
584+
resource.TestCheckResourceAttr(
585+
"argocd_application.info",
586+
"spec.0.info.0.value",
587+
value,
588+
),
589+
),
590+
},
591+
{
592+
Config: testAccArgoCDApplicationNoInfo(name),
593+
Check: resource.ComposeTestCheckFunc(
594+
resource.TestCheckResourceAttrSet(
595+
"argocd_application.info",
596+
"metadata.0.uid",
597+
),
598+
resource.TestCheckNoResourceAttr(
599+
"argocd_application.info",
600+
"spec.0.info",
601+
),
602+
),
603+
},
604+
{
605+
Config: testAccArgoCDApplicationInfoEmpty(name),
606+
ExpectError: regexp.MustCompile("info: cannot be empty."),
607+
Check: resource.ComposeTestCheckFunc(
608+
resource.TestCheckResourceAttrSet(
609+
"argocd_application.info",
610+
"metadata.0.uid",
611+
),
612+
resource.TestCheckNoResourceAttr(
613+
"argocd_application.info",
614+
"spec.0.info",
615+
),
616+
),
617+
},
618+
}})
619+
}
620+
505621
func testAccArgoCDApplicationSimple(name string) string {
506622
return fmt.Sprintf(`
507623
resource "argocd_application" "simple" {
@@ -1138,6 +1254,153 @@ resource "argocd_application" "simple" {
11381254
`, name, revision_history_limit)
11391255
}
11401256

1257+
func testAccArgoCDApplicationInfo(name, info, value string) string {
1258+
return fmt.Sprintf(`
1259+
resource "argocd_application" "info" {
1260+
metadata {
1261+
name = "%s"
1262+
namespace = "argocd"
1263+
labels = {
1264+
acceptance = "true"
1265+
}
1266+
}
1267+
1268+
spec {
1269+
info {
1270+
name = "%s"
1271+
value = "%s"
1272+
}
1273+
source {
1274+
repo_url = "https://github.com/argoproj/argocd-example-apps"
1275+
path = "guestbook"
1276+
target_revision = "HEAD"
1277+
}
1278+
1279+
destination {
1280+
server = "https://kubernetes.default.svc"
1281+
namespace = "default"
1282+
}
1283+
}
1284+
}
1285+
`, name, info, value)
1286+
}
1287+
1288+
func testAccArgoCDApplicationInfoNoName(name, value string) string {
1289+
return fmt.Sprintf(`
1290+
resource "argocd_application" "info" {
1291+
metadata {
1292+
name = "%s"
1293+
namespace = "argocd"
1294+
labels = {
1295+
acceptance = "true"
1296+
}
1297+
}
1298+
1299+
spec {
1300+
info {
1301+
value = "%s"
1302+
}
1303+
source {
1304+
repo_url = "https://github.com/argoproj/argocd-example-apps"
1305+
path = "guestbook"
1306+
target_revision = "HEAD"
1307+
}
1308+
1309+
destination {
1310+
server = "https://kubernetes.default.svc"
1311+
namespace = "default"
1312+
}
1313+
}
1314+
}
1315+
`, name, value)
1316+
}
1317+
1318+
func testAccArgoCDApplicationInfoNoValue(name, info string) string {
1319+
return fmt.Sprintf(`
1320+
resource "argocd_application" "info" {
1321+
metadata {
1322+
name = "%s"
1323+
namespace = "argocd"
1324+
labels = {
1325+
acceptance = "true"
1326+
}
1327+
}
1328+
1329+
spec {
1330+
info {
1331+
name = "%s"
1332+
}
1333+
source {
1334+
repo_url = "https://github.com/argoproj/argocd-example-apps"
1335+
path = "guestbook"
1336+
target_revision = "HEAD"
1337+
}
1338+
1339+
destination {
1340+
server = "https://kubernetes.default.svc"
1341+
namespace = "default"
1342+
}
1343+
}
1344+
}
1345+
`, name, info)
1346+
}
1347+
1348+
func testAccArgoCDApplicationInfoEmpty(name string) string {
1349+
return fmt.Sprintf(`
1350+
resource "argocd_application" "info" {
1351+
metadata {
1352+
name = "%s"
1353+
namespace = "argocd"
1354+
labels = {
1355+
acceptance = "true"
1356+
}
1357+
}
1358+
1359+
spec {
1360+
info {
1361+
}
1362+
source {
1363+
repo_url = "https://github.com/argoproj/argocd-example-apps"
1364+
path = "guestbook"
1365+
target_revision = "HEAD"
1366+
}
1367+
1368+
destination {
1369+
server = "https://kubernetes.default.svc"
1370+
namespace = "default"
1371+
}
1372+
}
1373+
}
1374+
`, name)
1375+
}
1376+
1377+
func testAccArgoCDApplicationNoInfo(name string) string {
1378+
return fmt.Sprintf(`
1379+
resource "argocd_application" "info" {
1380+
metadata {
1381+
name = "%s"
1382+
namespace = "argocd"
1383+
labels = {
1384+
acceptance = "true"
1385+
}
1386+
}
1387+
1388+
spec {
1389+
source {
1390+
repo_url = "https://github.com/argoproj/argocd-example-apps"
1391+
path = "guestbook"
1392+
target_revision = "HEAD"
1393+
}
1394+
1395+
destination {
1396+
server = "https://kubernetes.default.svc"
1397+
namespace = "default"
1398+
}
1399+
}
1400+
}
1401+
`, name)
1402+
}
1403+
11411404
func testAccSkipFeatureIgnoreDiffJQPathExpressions() (bool, error) {
11421405
p, _ := testAccProviders["argocd"]()
11431406
_ = p.Configure(context.Background(), &terraform.ResourceConfig{})

argocd/structure_application.go

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,19 @@ func expandApplicationSpec(d *schema.ResourceData) (
3636
spec.RevisionHistoryLimit = &pv
3737
}
3838
if v, ok := s["info"]; ok {
39-
spec.Info = expandApplicationInfo(v.(*schema.Set))
39+
spec.Info, diags = expandApplicationInfo(v.(*schema.Set))
40+
if len(diags) > 0 {
41+
return
42+
}
4043
}
4144
if v, ok := s["ignore_difference"]; ok {
4245
spec.IgnoreDifferences = expandApplicationIgnoreDifferences(v.([]interface{}))
4346
}
4447
if v, ok := s["sync_policy"]; ok {
4548
spec.SyncPolicy, diags = expandApplicationSyncPolicy(v.([]interface{}))
49+
if len(diags) > 0 {
50+
return
51+
}
4652
}
4753
if v, ok := s["destination"]; ok {
4854
spec.Destination = expandApplicationDestination(v.(*schema.Set).List()[0])
@@ -379,12 +385,30 @@ func expandApplicationIgnoreDifferences(ids []interface{}) (
379385
}
380386

381387
func expandApplicationInfo(infos *schema.Set) (
382-
result []application.Info) {
388+
result []application.Info, diags diag.Diagnostics) {
383389
for _, i := range infos.List() {
384-
result = append(result, application.Info{
385-
Name: i.(map[string]string)["name"],
386-
Value: i.(map[string]string)["value"],
387-
})
390+
item := i.(map[string]interface{})
391+
info := application.Info{}
392+
fieldSet := false
393+
394+
if name, ok := item["name"].(string); ok && name != "" {
395+
info.Name = name
396+
fieldSet = true
397+
}
398+
if value, ok := item["value"].(string); ok && value != "" {
399+
info.Value = value
400+
fieldSet = true
401+
}
402+
403+
if !fieldSet {
404+
diags = append(diags, diag.Diagnostic{
405+
Severity: diag.Error,
406+
Summary: "spec.info: cannot be empty. Must only contains 'name' or 'value' fields.",
407+
})
408+
return
409+
}
410+
411+
result = append(result, info)
388412
}
389413
return
390414
}
@@ -480,10 +504,16 @@ func flattenApplicationSyncPolicy(sp *application.SyncPolicy) []map[string]inter
480504
func flattenApplicationInfo(infos []application.Info) (
481505
result []map[string]string) {
482506
for _, i := range infos {
483-
result = append(result, map[string]string{
484-
"name": i.Name,
485-
"value": i.Value,
486-
})
507+
info := map[string]string{}
508+
509+
if i.Name != "" {
510+
info["name"] = i.Name
511+
}
512+
if i.Value != "" {
513+
info["value"] = i.Value
514+
}
515+
516+
result = append(result, info)
487517
}
488518
return
489519
}

0 commit comments

Comments
 (0)