From 2463f864ddabfa39ccd8ab882e09c465d2873d4a Mon Sep 17 00:00:00 2001 From: Daniel Banck Date: Tue, 26 Aug 2025 19:17:27 +0200 Subject: [PATCH] Exclude nested config block from list resource schemas (#37495) * Exclude nested config block from list resource schemas * Guard action schemas by experimental flag * Fix tests --- internal/command/jsonformat/plan_test.go | 2 +- internal/command/jsonprovider/provider.go | 16 +++++++-- .../command/jsonprovider/provider_test.go | 36 +++++++++++++++---- 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/internal/command/jsonformat/plan_test.go b/internal/command/jsonformat/plan_test.go index e47b63c89f..a0f59eaea1 100644 --- a/internal/command/jsonformat/plan_test.go +++ b/internal/command/jsonformat/plan_test.go @@ -8544,7 +8544,7 @@ func TestResourceChange_actions(t *testing.T) { }, }, } - jsonschemas := jsonprovider.MarshalForRenderer(fullSchema, false) + jsonschemas := jsonprovider.MarshalForRenderer(fullSchema, true) diffs := precomputeDiffs(Plan{ ResourceChanges: []jsonplan.ResourceChange{defaultResourceChange}, ActionInvocations: tc.actionInvocations, diff --git a/internal/command/jsonprovider/provider.go b/internal/command/jsonprovider/provider.go index fee03e6dd9..dbf31c757b 100644 --- a/internal/command/jsonprovider/provider.go +++ b/internal/command/jsonprovider/provider.go @@ -68,11 +68,23 @@ func marshalProvider(tps providers.ProviderSchema, includeExperimentalSchemas bo EphemeralResourceSchemas: marshalSchemas(tps.EphemeralResourceTypes), Functions: jsonfunction.MarshalProviderFunctions(tps.Functions), ResourceIdentitySchemas: marshalIdentitySchemas(tps.ResourceTypes), - ActionSchemas: marshalActionSchemas(tps.Actions), } if includeExperimentalSchemas { - p.ListResourceSchemas = marshalSchemas(tps.ListResourceTypes) + // List resource schemas are nested under a "config" block, so we need to + // extract that block to get the actual provider schema for the list resource. + // When getting the provider schemas, Terraform adds this extra level to + // better match the actual configuration structure. + listSchemas := make(map[string]providers.Schema, len(tps.ListResourceTypes)) + for k, v := range tps.ListResourceTypes { + listSchemas[k] = providers.Schema{ + Body: &v.Body.BlockTypes["config"].Block, + Version: v.Version, + } + } + p.ListResourceSchemas = marshalSchemas(listSchemas) + + p.ActionSchemas = marshalActionSchemas(tps.Actions) } return p diff --git a/internal/command/jsonprovider/provider_test.go b/internal/command/jsonprovider/provider_test.go index 4612df1571..c1de1ebb65 100644 --- a/internal/command/jsonprovider/provider_test.go +++ b/internal/command/jsonprovider/provider_test.go @@ -33,7 +33,6 @@ func TestMarshalProvider(t *testing.T) { DataSourceSchemas: map[string]*Schema{}, EphemeralResourceSchemas: map[string]*Schema{}, ResourceIdentitySchemas: map[string]*IdentitySchema{}, - ActionSchemas: map[string]*ActionSchema{}, }, }, { @@ -213,7 +212,6 @@ func TestMarshalProvider(t *testing.T) { }, }, ResourceIdentitySchemas: map[string]*IdentitySchema{}, - ActionSchemas: map[string]*ActionSchema{}, }, }, { @@ -223,8 +221,21 @@ func TestMarshalProvider(t *testing.T) { Version: 1, Body: &configschema.Block{ Attributes: map[string]*configschema.Attribute{ - "filter": {Type: cty.String, Optional: true}, - "items": {Type: cty.List(cty.String), Required: true}, + "data": { + Type: cty.DynamicPseudoType, + Computed: true, + }, + }, + BlockTypes: map[string]*configschema.NestedBlock{ + "config": { + Block: configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "filter": {Type: cty.String, Optional: true}, + "items": {Type: cty.List(cty.String), Required: true}, + }, + }, + Nesting: configschema.NestingSingle, + }, }, }, }, @@ -483,8 +494,21 @@ func testProvider() providers.ProviderSchema { Version: 1, Body: &configschema.Block{ Attributes: map[string]*configschema.Attribute{ - "filter": {Type: cty.String, Optional: true}, - "items": {Type: cty.List(cty.String), Required: true}, + "data": { + Type: cty.DynamicPseudoType, + Computed: true, + }, + }, + BlockTypes: map[string]*configschema.NestedBlock{ + "config": { + Block: configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "filter": {Type: cty.String, Optional: true}, + "items": {Type: cty.List(cty.String), Required: true}, + }, + }, + Nesting: configschema.NestingSingle, + }, }, }, },