Skip to content

Commit 46d0374

Browse files
committed
list: validate empty config
1 parent df11348 commit 46d0374

File tree

1 file changed

+103
-1
lines changed

1 file changed

+103
-1
lines changed

internal/terraform/context_plan_query_test.go

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,102 @@ func TestContext2Plan_queryList(t *testing.T) {
261261
}
262262
},
263263
},
264+
{
265+
name: "valid list with empty config",
266+
mainConfig: `
267+
terraform {
268+
required_providers {
269+
test = {
270+
source = "hashicorp/test"
271+
version = "1.0.0"
272+
}
273+
}
274+
}
275+
`,
276+
queryConfig: `
277+
variable "input" {
278+
type = string
279+
default = "foo"
280+
}
281+
282+
list "test_resource" "test" {
283+
provider = test
284+
}
285+
`,
286+
listResourceFn: func(request providers.ListResourceRequest) providers.ListResourceResponse {
287+
madeUp := []cty.Value{
288+
cty.ObjectVal(map[string]cty.Value{"instance_type": cty.StringVal("ami-123456")}),
289+
cty.ObjectVal(map[string]cty.Value{"instance_type": cty.StringVal("ami-654321")}),
290+
}
291+
ids := []cty.Value{}
292+
for i := range madeUp {
293+
ids = append(ids, cty.ObjectVal(map[string]cty.Value{
294+
"id": cty.StringVal(fmt.Sprintf("i-v%d", i+1)),
295+
}))
296+
}
297+
298+
resp := []cty.Value{}
299+
for i, v := range madeUp {
300+
resp = append(resp, cty.ObjectVal(map[string]cty.Value{
301+
"state": v,
302+
"identity": ids[i],
303+
"display_name": cty.StringVal(fmt.Sprintf("Instance %d", i+1)),
304+
}))
305+
}
306+
307+
ret := map[string]cty.Value{
308+
"data": cty.TupleVal(resp),
309+
}
310+
for k, v := range request.Config.AsValueMap() {
311+
if k != "data" {
312+
ret[k] = v
313+
}
314+
}
315+
316+
return providers.ListResourceResponse{Result: cty.ObjectVal(ret)}
317+
},
318+
assertChanges: func(sch providers.ProviderSchema, changes *plans.ChangesSrc) {
319+
expectedResources := []string{"list.test_resource.test"}
320+
actualResources := make([]string, 0)
321+
for _, change := range changes.Queries {
322+
actualResources = append(actualResources, change.Addr.String())
323+
schema := sch.ListResourceTypes[change.Addr.Resource.Resource.Type]
324+
cs, err := change.Decode(schema)
325+
if err != nil {
326+
t.Fatalf("failed to decode change: %s", err)
327+
}
328+
329+
// Verify instance types
330+
expectedTypes := []string{"ami-123456", "ami-654321"}
331+
actualTypes := make([]string, 0)
332+
obj := cs.Results.Value.GetAttr("data")
333+
if obj.IsNull() {
334+
t.Fatalf("Expected 'data' attribute to be present, but it is null")
335+
}
336+
obj.ForEachElement(func(key cty.Value, val cty.Value) bool {
337+
val = val.GetAttr("state")
338+
if val.IsNull() {
339+
t.Fatalf("Expected 'state' attribute to be present, but it is null")
340+
}
341+
if val.GetAttr("instance_type").IsNull() {
342+
t.Fatalf("Expected 'instance_type' attribute to be present, but it is missing")
343+
}
344+
actualTypes = append(actualTypes, val.GetAttr("instance_type").AsString())
345+
return false
346+
})
347+
sort.Strings(actualTypes)
348+
sort.Strings(expectedTypes)
349+
if diff := cmp.Diff(expectedTypes, actualTypes); diff != "" {
350+
t.Fatalf("Expected instance types to match, but they differ: %s", diff)
351+
}
352+
}
353+
sort.Strings(actualResources)
354+
sort.Strings(expectedResources)
355+
if diff := cmp.Diff(expectedResources, actualResources); diff != "" {
356+
t.Fatalf("Expected resources to match, but they differ: %s", diff)
357+
}
358+
},
359+
},
264360
{
265361
name: "invalid list result's attribute reference",
266362
mainConfig: `
@@ -690,6 +786,9 @@ func TestContext2Plan_queryList(t *testing.T) {
690786
provider.GetProviderSchemaResponse = getListProviderSchemaResp()
691787
var requestConfigs = make(map[string]cty.Value)
692788
provider.ListResourceFn = func(request providers.ListResourceRequest) providers.ListResourceResponse {
789+
if request.Config.IsNull() || request.Config.GetAttr("config").IsNull() {
790+
t.Fatalf("config should never be null, got null for %s", request.TypeName)
791+
}
693792
requestConfigs[request.TypeName] = request.Config
694793
fn := tc.listResourceFn
695794
if fn == nil {
@@ -837,6 +936,9 @@ func TestContext2Plan_queryListArgs(t *testing.T) {
837936
provider.GetProviderSchemaResponse = getListProviderSchemaResp()
838937
var recordedRequest providers.ListResourceRequest
839938
provider.ListResourceFn = func(request providers.ListResourceRequest) providers.ListResourceResponse {
939+
if request.Config.IsNull() || request.Config.GetAttr("config").IsNull() {
940+
t.Fatalf("config should never be null, got null for %s", request.TypeName)
941+
}
840942
recordedRequest = request
841943
return provider.ListResourceResponse
842944
}
@@ -902,7 +1004,7 @@ func getListProviderSchemaResp() *providers.GetProviderSchemaResponse {
9021004
},
9031005
},
9041006
},
905-
Nesting: configschema.NestingSingle,
1007+
Nesting: configschema.NestingGroup,
9061008
},
9071009
},
9081010
}

0 commit comments

Comments
 (0)