Skip to content

Commit f69a14d

Browse files
fix: validate agent & resource metadata keys during plan (#277)
1 parent 5f660a0 commit f69a14d

File tree

5 files changed

+59
-22
lines changed

5 files changed

+59
-22
lines changed

provider/agent.go

Lines changed: 26 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,32 @@ func agentResource() *schema.Resource {
272260
Optional: true,
273261
},
274262
},
263+
CustomizeDiff: func(ctx context.Context, rd *schema.ResourceDiff, i any) error {
264+
if !rd.HasChange("metadata") {
265+
return nil
266+
}
267+
268+
keys := map[string]bool{}
269+
metadata, ok := rd.Get("metadata").([]any)
270+
if !ok {
271+
return xerrors.Errorf("unexpected type %T for metadata, expected []any", rd.Get("metadata"))
272+
}
273+
for _, t := range metadata {
274+
obj, ok := t.(map[string]any)
275+
if !ok {
276+
return xerrors.Errorf("unexpected type %T for metadata, expected map[string]any", t)
277+
}
278+
key, ok := obj["key"].(string)
279+
if !ok {
280+
return xerrors.Errorf("unexpected type %T for metadata key, expected string", obj["key"])
281+
}
282+
if keys[key] {
283+
return xerrors.Errorf("duplicate agent metadata key %q", key)
284+
}
285+
keys[key] = true
286+
}
287+
return nil
288+
},
275289
}
276290
}
277291

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: 27 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 {
@@ -111,5 +112,31 @@ func metadataResource() *schema.Resource {
111112
},
112113
},
113114
},
115+
CustomizeDiff: func(ctx context.Context, rd *schema.ResourceDiff, i interface{}) error {
116+
if !rd.HasChange("item") {
117+
return nil
118+
}
119+
120+
keys := map[string]bool{}
121+
metadata, ok := rd.Get("item").([]any)
122+
if !ok {
123+
return xerrors.Errorf("unexpected type %T for items, expected []any", rd.Get("metadata"))
124+
}
125+
for _, t := range metadata {
126+
obj, ok := t.(map[string]any)
127+
if !ok {
128+
return xerrors.Errorf("unexpected type %T for item, expected map[string]any", t)
129+
}
130+
key, ok := obj["key"].(string)
131+
if !ok {
132+
return xerrors.Errorf("unexpected type %T for items 'key' attribute, expected string", obj["key"])
133+
}
134+
if keys[key] {
135+
return xerrors.Errorf("duplicate resource metadata key %q", key)
136+
}
137+
keys[key] = true
138+
}
139+
return nil
140+
},
114141
}
115142
}

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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy