Skip to content

Commit d672054

Browse files
committed
SchemaForListResourceType
1 parent 2247707 commit d672054

File tree

4 files changed

+40
-8
lines changed

4 files changed

+40
-8
lines changed

internal/providers/provider.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,19 @@ func (a ActionSchema) IsNil() bool {
220220
return a.ConfigSchema == nil
221221
}
222222

223+
type ListResourceSchema struct {
224+
// schema for the nested "config" block.
225+
ConfigSchema *configschema.Block
226+
227+
// schema for the entire block (including "config" block)
228+
FullSchema *configschema.Block
229+
}
230+
231+
// IsNil() returns true if there is no list resource schema at all.
232+
func (l ListResourceSchema) IsNil() bool {
233+
return l.FullSchema == nil
234+
}
235+
223236
// Schema pairs a provider or resource schema with that schema's version.
224237
// This is used to be able to upgrade the schema in UpgradeResourceState.
225238
//

internal/providers/schemas.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,18 @@ func (ss ProviderSchema) SchemaForActionType(typeName string) (schema ActionSche
4747
}
4848
return ActionSchema{}
4949
}
50+
51+
// SchemaForListResourceType attempts to find a schema for the given type. Returns an
52+
// empty schema if none is available.
53+
func (ss ProviderSchema) SchemaForListResourceType(typeName string) ListResourceSchema {
54+
schema, ok := ss.ListResourceTypes[typeName]
55+
if !ok || schema.Body == nil {
56+
return ListResourceSchema{}
57+
}
58+
// The configuration for the list block is nested within a "config" block.
59+
configSchema, ok := schema.Body.BlockTypes["config"]
60+
if !ok {
61+
return ListResourceSchema{}
62+
}
63+
return ListResourceSchema{ConfigSchema: &configSchema.Block, FullSchema: schema.Body}
64+
}

internal/terraform/node_resource_plan_instance_query.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,15 @@ func (n *NodePlannableResourceInstance) listResourceExecute(ctx EvalContext) (di
3636
keyData = EvalDataForInstanceKey(addr.Resource.Key, forEach)
3737
}
3838

39+
schema := providerSchema.SchemaForListResourceType(n.Config.Type)
40+
if schema.IsNil() { // Not possible, as the schema should have already been validated to exist
41+
diags = diags.Append(fmt.Errorf("no schema available for %s; this is a bug in Terraform and should be reported", addr))
42+
return diags
43+
}
44+
3945
// evaluate the list config block
4046
var configDiags tfdiags.Diagnostics
41-
blockVal, _, configDiags := ctx.EvaluateBlock(config.Config, n.Schema.Body, nil, keyData)
47+
blockVal, _, configDiags := ctx.EvaluateBlock(config.Config, schema.FullSchema, nil, keyData)
4248
diags = diags.Append(configDiags)
4349
if diags.HasErrors() {
4450
return diags
@@ -79,11 +85,10 @@ func (n *NodePlannableResourceInstance) listResourceExecute(ctx EvalContext) (di
7985
}
8086

8187
log.Printf("[TRACE] NodePlannableResourceInstance: Re-validating config for %s", n.Addr)
82-
configSchema := n.Schema.Body.BlockTypes["config"]
8388
// if the config value is null, we still want to send a full object with all attributes being null
8489
if !unmarkedBlockVal.IsNull() && unmarkedBlockVal.GetAttr("config").IsNull() {
8590
mp := unmarkedBlockVal.AsValueMap()
86-
mp["config"] = configSchema.Block.EmptyValue()
91+
mp["config"] = schema.ConfigSchema.EmptyValue()
8792
unmarkedBlockVal = cty.ObjectVal(mp)
8893
}
8994

internal/terraform/node_resource_validate.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -471,8 +471,8 @@ func (n *NodeValidatableResource) validateResource(ctx EvalContext) tfdiags.Diag
471471
resp := provider.ValidateEphemeralResourceConfig(req)
472472
diags = diags.Append(resp.Diagnostics.InConfigBody(n.Config.Config, n.Addr.String()))
473473
case addrs.ListResourceMode:
474-
schema := providerSchema.SchemaForResourceType(n.Config.Mode, n.Config.Type)
475-
if schema.Body == nil {
474+
schema := providerSchema.SchemaForListResourceType(n.Config.Type)
475+
if schema.IsNil() {
476476
diags = diags.Append(&hcl.Diagnostic{
477477
Severity: hcl.DiagError,
478478
Summary: "Invalid list resource",
@@ -482,7 +482,7 @@ func (n *NodeValidatableResource) validateResource(ctx EvalContext) tfdiags.Diag
482482
return diags
483483
}
484484

485-
blockVal, _, valDiags := ctx.EvaluateBlock(n.Config.Config, schema.Body, nil, keyData)
485+
blockVal, _, valDiags := ctx.EvaluateBlock(n.Config.Config, schema.FullSchema, nil, keyData)
486486
diags = diags.Append(valDiags)
487487
if valDiags.HasErrors() {
488488
return diags
@@ -503,11 +503,10 @@ func (n *NodeValidatableResource) validateResource(ctx EvalContext) tfdiags.Diag
503503
// Use unmarked value for validate request
504504
unmarkedBlockVal, _ := blockVal.UnmarkDeep()
505505

506-
configSchema := schema.Body.BlockTypes["config"]
507506
// if the config value is null, we still want to send a full object with all attributes being null
508507
if !unmarkedBlockVal.IsNull() && unmarkedBlockVal.GetAttr("config").IsNull() {
509508
mp := unmarkedBlockVal.AsValueMap()
510-
mp["config"] = configSchema.Block.EmptyValue()
509+
mp["config"] = schema.ConfigSchema.EmptyValue()
511510
unmarkedBlockVal = cty.ObjectVal(mp)
512511
}
513512
req := providers.ValidateListResourceConfigRequest{

0 commit comments

Comments
 (0)