Skip to content

Commit 8b21788

Browse files
authored
Support arbitrary nested values for edge_config_item (#390)
1 parent 81e5f9b commit 8b21788

File tree

9 files changed

+428
-52
lines changed

9 files changed

+428
-52
lines changed

client/edge_config_item.go

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,33 @@ package client
22

33
import (
44
"context"
5+
"encoding/json"
56
"fmt"
67

78
"github.com/hashicorp/terraform-plugin-log/tflog"
89
)
910

1011
type EdgeConfigOperation struct {
11-
Operation string `json:"operation"`
12-
Key string `json:"key"`
13-
Value string `json:"value"`
12+
Operation string `json:"operation"`
13+
Key string `json:"key"`
14+
Value json.RawMessage `json:"value,omitempty"`
1415
}
1516

1617
type EdgeConfigItem struct {
17-
TeamID string
18-
Key string `json:"key"`
19-
Value string `json:"value"`
20-
EdgeConfigID string `json:"edgeConfigId"`
18+
TeamID string `json:"-"`
19+
Key string `json:"key"`
20+
Value json.RawMessage `json:"value"`
21+
EdgeConfigID string `json:"edgeConfigId"`
2122
}
2223

2324
type CreateEdgeConfigItemRequest struct {
2425
EdgeConfigID string
2526
TeamID string
2627
Key string
27-
Value string
28+
// Value should be a valid JSON encoding of the item value. For strings,
29+
// include quotes (e.g. "\"hello\""). For objects/arrays/numbers/bools/null,
30+
// provide the raw JSON representation.
31+
Value json.RawMessage
2832
}
2933

3034
func (c *Client) CreateEdgeConfigItem(ctx context.Context, request CreateEdgeConfigItemRequest) (e EdgeConfigItem, err error) {
@@ -70,7 +74,6 @@ type EdgeConfigItemRequest struct {
7074
EdgeConfigID string
7175
TeamID string
7276
Key string
73-
Value string
7477
}
7578

7679
func (c *Client) DeleteEdgeConfigItem(ctx context.Context, request EdgeConfigItemRequest) error {
@@ -87,7 +90,6 @@ func (c *Client) DeleteEdgeConfigItem(ctx context.Context, request EdgeConfigIte
8790
{
8891
Operation: "delete",
8992
Key: request.Key,
90-
Value: request.Value,
9193
},
9294
},
9395
},

docs/data-sources/edge_config_item.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,17 @@ data "vercel_edge_config" "example" {
2323
id = "ecfg_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
2424
}
2525
26-
data "vercel_edge_config_item" "test" {
26+
# Read a string item
27+
data "vercel_edge_config_item" "string_item" {
2728
id = data.vercel_edge_config.example.id
2829
key = "foobar"
2930
}
31+
32+
# Read a JSON item
33+
data "vercel_edge_config_item" "json_item" {
34+
id = data.vercel_edge_config.example.id
35+
key = "flags"
36+
}
3037
```
3138

3239
<!-- schema generated by tfplugindocs -->
@@ -43,4 +50,5 @@ data "vercel_edge_config_item" "test" {
4350

4451
### Read-Only
4552

46-
- `value` (String) The value assigned to the key.
53+
- `value` (String) The value assigned to the key (only set for string values).
54+
- `value_json` (Dynamic) Structured JSON value (object/array/number/bool/null) assigned to the key.

docs/resources/edge_config_item.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@ resource "vercel_edge_config" "example" {
2525
2626
resource "vercel_edge_config_item" "example" {
2727
edge_config_id = vercel_edge_config.example.id
28-
key = "foobar"
29-
value = "baz"
28+
key = "flags"
29+
value_json = {
30+
featureA = true
31+
nested = { a = 1, b = [1, 2, 3] }
32+
}
3033
}
3134
```
3235

@@ -37,11 +40,12 @@ resource "vercel_edge_config_item" "example" {
3740

3841
- `edge_config_id` (String) The ID of the Edge Config store.
3942
- `key` (String) The name of the key you want to add to or update within your Edge Config.
40-
- `value` (String) The value you want to assign to the key.
4143

4244
### Optional
4345

4446
- `team_id` (String) The ID of the team the Edge Config should exist under. Required when configuring a team resource if a default team has not been set in the provider.
47+
- `value` (String) The value you want to assign to the key when using a string.
48+
- `value_json` (Dynamic) Structured JSON value to assign to the key (object/array/number/bool/null).
4549

4650
## Import
4751

examples/data-sources/vercel_edge_config_item/data-source.tf

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,14 @@ data "vercel_edge_config" "example" {
22
id = "ecfg_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
33
}
44

5-
data "vercel_edge_config_item" "test" {
5+
# Read a string item
6+
data "vercel_edge_config_item" "string_item" {
67
id = data.vercel_edge_config.example.id
78
key = "foobar"
89
}
10+
11+
# Read a JSON item
12+
data "vercel_edge_config_item" "json_item" {
13+
id = data.vercel_edge_config.example.id
14+
key = "flags"
15+
}

examples/resources/vercel_edge_config_item/resource.tf

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ resource "vercel_edge_config" "example" {
44

55
resource "vercel_edge_config_item" "example" {
66
edge_config_id = vercel_edge_config.example.id
7-
key = "foobar"
8-
value = "baz"
7+
key = "flags"
8+
value_json = {
9+
featureA = true
10+
nested = { a = 1, b = [1, 2, 3] }
11+
}
912
}

vercel/data_source_edge_config_item.go

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ package vercel
22

33
import (
44
"context"
5+
"encoding/json"
56
"fmt"
67

78
"github.com/hashicorp/terraform-plugin-framework/datasource"
89
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
910
"github.com/hashicorp/terraform-plugin-framework/types"
11+
"github.com/hashicorp/terraform-plugin-go/tftypes"
1012
"github.com/hashicorp/terraform-plugin-log/tflog"
1113
"github.com/vercel/terraform-provider-vercel/v3/client"
1214
)
@@ -71,18 +73,23 @@ An Edge Config Item is a value within an Edge Config.`,
7173
Required: true,
7274
},
7375
"value": schema.StringAttribute{
74-
Description: "The value assigned to the key.",
76+
Description: "The value assigned to the key (only set for string values).",
77+
Computed: true,
78+
},
79+
"value_json": schema.DynamicAttribute{
80+
Description: "Structured JSON value (object/array/number/bool/null) assigned to the key.",
7581
Computed: true,
7682
},
7783
},
7884
}
7985
}
8086

8187
type EdgeConfigItemDataSource struct {
82-
EdgeConfigID types.String `tfsdk:"id"`
83-
TeamID types.String `tfsdk:"team_id"`
84-
Key types.String `tfsdk:"key"`
85-
Value types.String `tfsdk:"value"`
88+
EdgeConfigID types.String `tfsdk:"id"`
89+
TeamID types.String `tfsdk:"team_id"`
90+
Key types.String `tfsdk:"key"`
91+
Value types.String `tfsdk:"value"`
92+
ValueJSON types.Dynamic `tfsdk:"value_json"`
8693
}
8794

8895
// Read will read the edgeConfigItem information by requesting it from the Vercel API, and will update terraform
@@ -113,14 +120,39 @@ func (d *edgeConfigItemDataSource) Read(ctx context.Context, req datasource.Read
113120
return
114121
}
115122

116-
result := responseToEdgeConfigItem(out)
123+
// Parse API value
124+
var result EdgeConfigItemDataSource
125+
result.EdgeConfigID = types.StringValue(out.EdgeConfigID)
126+
result.TeamID = types.StringValue(out.TeamID)
127+
result.Key = types.StringValue(out.Key)
128+
if len(out.Value) > 0 {
129+
var sv string
130+
if err := json.Unmarshal(out.Value, &sv); err == nil {
131+
result.Value = types.StringValue(sv)
132+
result.ValueJSON = types.DynamicNull()
133+
} else {
134+
tfval, err := tftypes.ValueFromJSONWithOpts(out.Value, tftypes.DynamicPseudoType, tftypes.ValueFromJSONOpts{IgnoreUndefinedAttributes: true})
135+
if err != nil {
136+
resp.Diagnostics.AddError("Error parsing Edge Config Item value", err.Error())
137+
return
138+
}
139+
av, err := types.DynamicType.ValueFromTerraform(ctx, tfval)
140+
if err != nil {
141+
resp.Diagnostics.AddError("Error converting Edge Config Item value", err.Error())
142+
return
143+
}
144+
result.Value = types.StringNull()
145+
result.ValueJSON = av.(types.Dynamic)
146+
}
147+
}
148+
117149
tflog.Info(ctx, "read edge config item", map[string]any{
118150
"edge_config_id": result.EdgeConfigID.ValueString(),
119151
"team_id": result.TeamID.ValueString(),
120152
"key": result.Key.ValueString(),
121153
})
122154

123-
diags = resp.State.Set(ctx, EdgeConfigItemDataSource(result))
155+
diags = resp.State.Set(ctx, result)
124156
resp.Diagnostics.Append(diags...)
125157
if resp.Diagnostics.HasError() {
126158
return

vercel/data_source_project_deployment_retention_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ func TestAcc_ProjectDeploymentRetentionDataSource(t *testing.T) {
2525
resource.TestCheckResourceAttr("data.vercel_project_deployment_retention.example", "expiration_canceled", "unlimited"),
2626
resource.TestCheckResourceAttr("data.vercel_project_deployment_retention.example", "expiration_errored", "unlimited"),
2727

28-
resource.TestCheckResourceAttr("data.vercel_project_deployment_retention.example_2", "expiration_preview", "unlimited"),
29-
resource.TestCheckResourceAttr("data.vercel_project_deployment_retention.example_2", "expiration_production", "unlimited"),
30-
resource.TestCheckResourceAttr("data.vercel_project_deployment_retention.example_2", "expiration_canceled", "unlimited"),
31-
resource.TestCheckResourceAttr("data.vercel_project_deployment_retention.example_2", "expiration_errored", "unlimited"),
28+
resource.TestCheckResourceAttrSet("data.vercel_project_deployment_retention.example_2", "expiration_preview"),
29+
resource.TestCheckResourceAttrSet("data.vercel_project_deployment_retention.example_2", "expiration_production"),
30+
resource.TestCheckResourceAttrSet("data.vercel_project_deployment_retention.example_2", "expiration_canceled"),
31+
resource.TestCheckResourceAttrSet("data.vercel_project_deployment_retention.example_2", "expiration_errored"),
3232
),
3333
},
3434
},

0 commit comments

Comments
 (0)