Skip to content

Commit 6b8265e

Browse files
authored
Merge pull request #624 from hashicorp/terraform-33757
Check for duplicate keys in objects when building types from expressions
2 parents 3617411 + 4259e4b commit 6b8265e

2 files changed

Lines changed: 40 additions & 2 deletions

File tree

ext/typeexpr/get_type.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ package typeexpr
66
import (
77
"fmt"
88

9-
"github.com/hashicorp/hcl/v2"
109
"github.com/zclconf/go-cty/cty"
1110
"github.com/zclconf/go-cty/cty/convert"
11+
12+
"github.com/hashicorp/hcl/v2"
1213
)
1314

1415
const invalidTypeSummary = "Invalid type specification"
@@ -179,6 +180,18 @@ func getType(expr hcl.Expression, constraint, withDefaults bool) (cty.Type, *Def
179180
})
180181
continue
181182
}
183+
184+
if _, exists := atys[attrName]; exists {
185+
diags = append(diags, &hcl.Diagnostic{
186+
Severity: hcl.DiagError,
187+
Summary: invalidTypeSummary,
188+
Detail: "Object constructor map keys must be unique.",
189+
Subject: attrDef.Key.Range().Ptr(),
190+
Context: expr.Range().Ptr(),
191+
})
192+
continue
193+
}
194+
182195
atyExpr := attrDef.Value
183196

184197
// the attribute type expression might be wrapped in the special

ext/typeexpr/get_type_test.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ import (
1010
"github.com/hashicorp/hcl/v2/gohcl"
1111

1212
"github.com/google/go-cmp/cmp"
13+
"github.com/zclconf/go-cty/cty"
14+
1315
"github.com/hashicorp/hcl/v2"
1416
"github.com/hashicorp/hcl/v2/hclsyntax"
1517
"github.com/hashicorp/hcl/v2/json"
16-
"github.com/zclconf/go-cty/cty"
1718
)
1819

1920
var (
@@ -700,6 +701,30 @@ func TestGetTypeDefaults(t *testing.T) {
700701
nil,
701702
`Optional attribute modifier expects at most two arguments: the attribute type, and a default value.`,
702703
},
704+
705+
// Duplicate arguments.
706+
{
707+
`map(object({operations=optional(list(string), []),type=optional(string, "ABC"),type=optional(number)}))`,
708+
&Defaults{
709+
Type: cty.Map(cty.ObjectWithOptionalAttrs(map[string]cty.Type{
710+
"operations": cty.List(cty.String),
711+
"type": cty.String,
712+
}, []string{"operations", "type"})),
713+
Children: map[string]*Defaults{
714+
"": {
715+
Type: cty.ObjectWithOptionalAttrs(map[string]cty.Type{
716+
"operations": cty.List(cty.String),
717+
"type": cty.String,
718+
}, []string{"operations", "type"}),
719+
DefaultValues: map[string]cty.Value{
720+
"operations": cty.ListValEmpty(cty.String),
721+
"type": cty.StringVal("ABC"),
722+
},
723+
},
724+
},
725+
},
726+
"Object constructor map keys must be unique.",
727+
},
703728
}
704729

705730
for _, test := range tests {

0 commit comments

Comments
 (0)