Skip to content

Commit dcac3db

Browse files
committed
fix: validate agent & resource metadata keys during plan
1 parent 1d525fa commit dcac3db

File tree

5 files changed

+41
-22
lines changed

5 files changed

+41
-22
lines changed

provider/agent.go

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,6 @@ func agentResource() *schema.Resource {
4343
}
4444
}
4545

46-
rawPlan := resourceData.GetRawPlan()
47-
items := rawPlan.GetAttr("metadata").AsValueSlice()
48-
itemKeys := map[string]struct{}{}
49-
for _, item := range items {
50-
key := valueAsString(item.GetAttr("key"))
51-
_, exists := itemKeys[key]
52-
if exists {
53-
return diag.FromErr(xerrors.Errorf("duplicate agent metadata key %q", key))
54-
}
55-
itemKeys[key] = struct{}{}
56-
}
57-
5846
return updateInitScript(resourceData, i)
5947
},
6048
ReadWithoutTimeout: func(ctx context.Context, resourceData *schema.ResourceData, i interface{}) diag.Diagnostics {
@@ -272,6 +260,23 @@ func agentResource() *schema.Resource {
272260
Optional: true,
273261
},
274262
},
263+
CustomizeDiff: func(ctx context.Context, rd *schema.ResourceDiff, i interface{}) error {
264+
if !rd.HasChange("metadata") {
265+
return nil
266+
}
267+
268+
keys := map[string]struct{}{}
269+
for _, t := range rd.Get("metadata").([]interface{}) {
270+
taint := t.(map[string]interface{})
271+
key := taint["key"].(string)
272+
_, ok := keys[key]
273+
if ok {
274+
return xerrors.Errorf("duplicate agent metadata key %q", key)
275+
}
276+
keys[key] = struct{}{}
277+
}
278+
return nil
279+
},
275280
}
276281
}
277282

provider/agent_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ func TestAgent_MetadataDuplicateKeys(t *testing.T) {
254254
}
255255
`,
256256
ExpectError: regexp.MustCompile("duplicate agent metadata key"),
257+
PlanOnly: true,
257258
}},
258259
})
259260
}
@@ -281,7 +282,7 @@ func TestAgent_DisplayApps(t *testing.T) {
281282
web_terminal = false
282283
port_forwarding_helper = false
283284
ssh_helper = false
284-
}
285+
}
285286
}
286287
`,
287288
Check: func(state *terraform.State) error {
@@ -331,7 +332,7 @@ func TestAgent_DisplayApps(t *testing.T) {
331332
display_apps {
332333
vscode_insiders = true
333334
web_terminal = true
334-
}
335+
}
335336
}
336337
`,
337338
Check: func(state *terraform.State) error {
@@ -426,7 +427,7 @@ func TestAgent_DisplayApps(t *testing.T) {
426427
web_terminal = false
427428
port_forwarding_helper = false
428429
ssh_helper = false
429-
}
430+
}
430431
}
431432
`,
432433
ExpectError: regexp.MustCompile(`An argument named "fake_app" is not expected here.`),

provider/metadata.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"github.com/google/uuid"
88
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
99
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
10+
"golang.org/x/xerrors"
1011
)
1112

1213
func metadataResource() *schema.Resource {
@@ -109,5 +110,22 @@ func metadataResource() *schema.Resource {
109110
},
110111
},
111112
},
113+
CustomizeDiff: func(ctx context.Context, rd *schema.ResourceDiff, i interface{}) error {
114+
if !rd.HasChange("item") {
115+
return nil
116+
}
117+
118+
keys := map[string]struct{}{}
119+
for _, t := range rd.Get("item").([]interface{}) {
120+
taint := t.(map[string]interface{})
121+
key := taint["key"].(string)
122+
_, ok := keys[key]
123+
if ok {
124+
return xerrors.Errorf("duplicate resource metadata key %q", key)
125+
}
126+
keys[key] = struct{}{}
127+
}
128+
return nil
129+
},
112130
}
113131
}

provider/metadata_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ func TestMetadataDuplicateKeys(t *testing.T) {
123123
}
124124
}
125125
`,
126-
ExpectError: regexp.MustCompile("duplicate metadata key"),
126+
PlanOnly: true,
127+
ExpectError: regexp.MustCompile("duplicate resource metadata key"),
127128
}},
128129
})
129130
}

provider/provider.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,14 +97,8 @@ func populateIsNull(resourceData *schema.ResourceData) (result interface{}, err
9797
items := rawPlan.GetAttr("item").AsValueSlice()
9898

9999
var resultItems []interface{}
100-
itemKeys := map[string]struct{}{}
101100
for _, item := range items {
102101
key := valueAsString(item.GetAttr("key"))
103-
_, exists := itemKeys[key]
104-
if exists {
105-
return nil, xerrors.Errorf("duplicate metadata key %q", key)
106-
}
107-
itemKeys[key] = struct{}{}
108102
resultItem := map[string]interface{}{
109103
"key": key,
110104
"value": valueAsString(item.GetAttr("value")),

0 commit comments

Comments
 (0)