Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions helm/resource_helm_release.go
Original file line number Diff line number Diff line change
Expand Up @@ -1280,8 +1280,8 @@ func getValues(ctx context.Context, model *HelmReleaseModel) (map[string]interfa
if !model.Set.IsNull() {
tflog.Debug(ctx, "Processing Set attribute")
var setList []setResourceModel
setDiags := model.Set.ElementsAs(ctx, &setList, false)
diags.Append(setDiags...)
diags.Append(model.Set.ElementsAs(ctx, &setList, false)...)
diags.Append(validateNoDuplicateSetNames(setList)...)
if diags.HasError() {
return nil, diags
}
Expand Down Expand Up @@ -2175,3 +2175,27 @@ func valuesUnknown(plan HelmReleaseModel) bool {
}
return false
}

// validateNoDuplicateSetNames checks for duplicate names in set blocks and returns
// an error diagnostic if any are found.
func validateNoDuplicateSetNames(setList []setResourceModel) diag.Diagnostics {
var diags diag.Diagnostics
seenNames := make(map[string]int)

for i, set := range setList {
name := set.Name.ValueString()

if prevIndex, seen := seenNames[name]; seen {
diags.AddError(
"Duplicate value name in set",
fmt.Sprintf("The name '%s' is specified multiple times in 'set' blocks (at indices %d and %d). "+
"Each name should only be specified once.", name, prevIndex, i),
)
return diags
}

seenNames[name] = i
}

return diags
}
47 changes: 47 additions & 0 deletions helm/resource_helm_release_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,25 @@ func TestAccResourceRelease_updateSetValue(t *testing.T) {
})
}

func TestAccResourceRelease_duplicateSetNames(t *testing.T) {
name := randName("test-duplicate-set-names")
namespace := createRandomNamespace(t)
defer deleteNamespace(t, namespace)

resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: protoV6ProviderFactories(),
Steps: []resource.TestStep{
{
// Config with duplicate set names should fail
Config: testAccHelmReleaseConfigDuplicateSetNames(
testResourceName, namespace, name, "1.2.3",
),
ExpectError: regexp.MustCompile("Duplicate value name in set"),
},
},
})
}

func TestAccResourceRelease_validation(t *testing.T) {
invalidName := "this-helm-release-name-is-longer-than-53-characters-long"
namespace := createRandomNamespace(t)
Expand Down Expand Up @@ -1038,6 +1057,34 @@ func testAccHelmReleaseConfigSet(resource, ns, name, version, setValue string) s
`, resource, name, ns, testRepositoryURL, version, setValue)
}

func testAccHelmReleaseConfigDuplicateSetNames(resource, ns, name, version string) string {
return fmt.Sprintf(`
resource "helm_release" "%s" {
name = %q
namespace = %q
description = "Test"
repository = %q
chart = "test-chart"
version = %q

set = [
{
name = "foo"
value = "bar"
},
{
name = "fizz"
value = "buzz"
},
{
name = "foo"
value = "different value"
}
]
}
`, resource, name, ns, testRepositoryURL, version)
}

func testAccHelmReleaseConfigSetNull(resource, ns, name, version string) string {
return fmt.Sprintf(`
resource "helm_release" "%s" {
Expand Down