diff --git a/internal/command/jsonformat/plan_test.go b/internal/command/jsonformat/plan_test.go index 47a7476899da..2a13806141bd 100644 --- a/internal/command/jsonformat/plan_test.go +++ b/internal/command/jsonformat/plan_test.go @@ -7899,7 +7899,7 @@ func runTestCases(t *testing.T, testCases map[string]testCase) { return } - jsonschemas := jsonprovider.MarshalForRenderer(tfschemas) + jsonschemas := jsonprovider.MarshalForRenderer(tfschemas, false) change := structured.FromJsonChange(jsonchanges[0].Change, attribute_path.AlwaysMatcher()) renderer := Renderer{Colorize: color} diff := diff{ @@ -8249,7 +8249,7 @@ func TestResourceChange_deferredActions(t *testing.T) { } renderer := Renderer{Colorize: color} - jsonschemas := jsonprovider.MarshalForRenderer(fullSchema) + jsonschemas := jsonprovider.MarshalForRenderer(fullSchema, false) diffs := precomputeDiffs(Plan{ DeferredChanges: deferredChanges, ProviderSchemas: jsonschemas, diff --git a/internal/command/jsonformat/state_test.go b/internal/command/jsonformat/state_test.go index f4f5c3a23498..2a4e3979f690 100644 --- a/internal/command/jsonformat/state_test.go +++ b/internal/command/jsonformat/state_test.go @@ -88,7 +88,7 @@ func TestState(t *testing.T) { RootModule: root, RootModuleOutputs: outputs, ProviderFormatVersion: jsonprovider.FormatVersion, - ProviderSchemas: jsonprovider.MarshalForRenderer(tt.Schemas), + ProviderSchemas: jsonprovider.MarshalForRenderer(tt.Schemas, false), }) result := done(t).All() diff --git a/internal/command/jsonprovider/provider.go b/internal/command/jsonprovider/provider.go index e87c02206362..e4c9bf4fba0a 100644 --- a/internal/command/jsonprovider/provider.go +++ b/internal/command/jsonprovider/provider.go @@ -27,6 +27,7 @@ type Provider struct { ResourceSchemas map[string]*Schema `json:"resource_schemas,omitempty"` DataSourceSchemas map[string]*Schema `json:"data_source_schemas,omitempty"` EphemeralResourceSchemas map[string]*Schema `json:"ephemeral_resource_schemas,omitempty"` + ListResourceSchemas map[string]*Schema `json:"list_resource_schemas,omitempty"` Functions map[string]*jsonfunction.FunctionSignature `json:"functions,omitempty"` ResourceIdentitySchemas map[string]*IdentitySchema `json:"resource_identity_schemas,omitempty"` } @@ -43,23 +44,23 @@ func newProviders() *Providers { // schema into the public structured JSON versions. // // This is a format that can be read by the structured plan renderer. -func MarshalForRenderer(s *terraform.Schemas) map[string]*Provider { +func MarshalForRenderer(s *terraform.Schemas, includeExperimentalSchemas bool) map[string]*Provider { schemas := make(map[string]*Provider, len(s.Providers)) for k, v := range s.Providers { - schemas[k.String()] = marshalProvider(v) + schemas[k.String()] = marshalProvider(v, includeExperimentalSchemas) } return schemas } -func Marshal(s *terraform.Schemas) ([]byte, error) { +func Marshal(s *terraform.Schemas, includeExperimentalSchemas bool) ([]byte, error) { providers := newProviders() - providers.Schemas = MarshalForRenderer(s) + providers.Schemas = MarshalForRenderer(s, includeExperimentalSchemas) ret, err := json.Marshal(providers) return ret, err } -func marshalProvider(tps providers.ProviderSchema) *Provider { - return &Provider{ +func marshalProvider(tps providers.ProviderSchema, includeExperimentalSchemas bool) *Provider { + p := &Provider{ Provider: marshalSchema(tps.Provider), ResourceSchemas: marshalSchemas(tps.ResourceTypes), DataSourceSchemas: marshalSchemas(tps.DataSources), @@ -67,4 +68,10 @@ func marshalProvider(tps providers.ProviderSchema) *Provider { Functions: jsonfunction.MarshalProviderFunctions(tps.Functions), ResourceIdentitySchemas: marshalIdentitySchemas(tps.ResourceTypes), } + + if includeExperimentalSchemas { + p.ListResourceSchemas = marshalSchemas(tps.ListResourceTypes) + } + + return p } diff --git a/internal/command/jsonprovider/provider_test.go b/internal/command/jsonprovider/provider_test.go index 162370c537cb..93063d2beb92 100644 --- a/internal/command/jsonprovider/provider_test.go +++ b/internal/command/jsonprovider/provider_test.go @@ -20,11 +20,13 @@ var cmpOpts = cmpopts.IgnoreUnexported(Provider{}) func TestMarshalProvider(t *testing.T) { tests := []struct { - Input providers.ProviderSchema - Want *Provider + Input providers.ProviderSchema + IncludeExperimental bool + Want *Provider }{ { providers.ProviderSchema{}, + false, &Provider{ Provider: &Schema{}, ResourceSchemas: map[string]*Schema{}, @@ -35,6 +37,7 @@ func TestMarshalProvider(t *testing.T) { }, { testProvider(), + false, &Provider{ Provider: &Schema{ Block: &Block{ @@ -211,11 +214,54 @@ func TestMarshalProvider(t *testing.T) { ResourceIdentitySchemas: map[string]*IdentitySchema{}, }, }, + { + providers.ProviderSchema{ + ListResourceTypes: map[string]providers.Schema{ + "test_list_resource": { + Version: 1, + Body: &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "filter": {Type: cty.String, Optional: true}, + "items": {Type: cty.List(cty.String), Required: true}, + }, + }, + }, + }, + }, + true, + &Provider{ + Provider: &Schema{}, + ResourceSchemas: map[string]*Schema{}, + DataSourceSchemas: map[string]*Schema{}, + EphemeralResourceSchemas: map[string]*Schema{}, + ListResourceSchemas: map[string]*Schema{ + "test_list_resource": { + Version: 1, + Block: &Block{ + Attributes: map[string]*Attribute{ + "filter": { + AttributeType: json.RawMessage(`"string"`), + Optional: true, + DescriptionKind: "plain", + }, + "items": { + AttributeType: json.RawMessage(`["list","string"]`), + Required: true, + DescriptionKind: "plain", + }, + }, + DescriptionKind: "plain", + }, + }, + }, + ResourceIdentitySchemas: map[string]*IdentitySchema{}, + }, + }, } for i, test := range tests { t.Run(fmt.Sprint(i), func(t *testing.T) { - got := marshalProvider(test.Input) + got := marshalProvider(test.Input, test.IncludeExperimental) if diff := cmp.Diff(test.Want, got, cmpOpts); diff != "" { t.Fatalf("wrong result:\n %s\n", diff) } @@ -317,5 +363,16 @@ func testProvider() providers.ProviderSchema { }, }, }, + ListResourceTypes: map[string]providers.Schema{ + "test_list_resource": { + Version: 1, + Body: &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "filter": {Type: cty.String, Optional: true}, + "items": {Type: cty.List(cty.String), Required: true}, + }, + }, + }, + }, } } diff --git a/internal/command/providers_schema.go b/internal/command/providers_schema.go index 807ad027e94c..0d51769133d3 100644 --- a/internal/command/providers_schema.go +++ b/internal/command/providers_schema.go @@ -107,7 +107,7 @@ func (c *ProvidersSchemaCommand) Run(args []string) int { return 1 } - jsonSchemas, err := jsonprovider.Marshal(schemas) + jsonSchemas, err := jsonprovider.Marshal(schemas, c.AllowExperimentalFeatures) if err != nil { c.Ui.Error(fmt.Sprintf("Failed to marshal provider schemas to json: %s", err)) return 1 @@ -120,6 +120,6 @@ func (c *ProvidersSchemaCommand) Run(args []string) int { const providersSchemaCommandHelp = ` Usage: terraform [global options] providers schema -json - Prints out a json representation of the schemas for all providers used + Prints out a json representation of the schemas for all providers used in the current configuration. ` diff --git a/internal/command/state_show.go b/internal/command/state_show.go index ec50449d8cd7..78c04c35a26a 100644 --- a/internal/command/state_show.go +++ b/internal/command/state_show.go @@ -155,7 +155,7 @@ func (c *StateShowCommand) Run(args []string) int { ProviderFormatVersion: jsonprovider.FormatVersion, RootModule: root, RootModuleOutputs: outputs, - ProviderSchemas: jsonprovider.MarshalForRenderer(schemas), + ProviderSchemas: jsonprovider.MarshalForRenderer(schemas, false), } renderer := jsonformat.Renderer{ @@ -195,11 +195,11 @@ func (c *StateShowCommand) Synopsis() string { const errNoInstanceFound = `No instance found for the given address! This command requires that the address references one specific instance. -To view the available instances, use "terraform state list". Please modify +To view the available instances, use "terraform state list". Please modify the address to reference a specific instance.` const errParsingAddress = `Error parsing instance address: %s This command requires that the address references one specific instance. -To view the available instances, use "terraform state list". Please modify +To view the available instances, use "terraform state list". Please modify the address to reference a specific instance.` diff --git a/internal/command/views/operation.go b/internal/command/views/operation.go index 46350b320fd4..b5e0d388a353 100644 --- a/internal/command/views/operation.go +++ b/internal/command/views/operation.go @@ -110,7 +110,7 @@ func (v *OperationHuman) Plan(plan *plans.Plan, schemas *terraform.Schemas) { OutputChanges: outputs, ResourceChanges: changed, ResourceDrift: drift, - ProviderSchemas: jsonprovider.MarshalForRenderer(schemas), + ProviderSchemas: jsonprovider.MarshalForRenderer(schemas, false), RelevantAttributes: attrs, } diff --git a/internal/command/views/show.go b/internal/command/views/show.go index e5ab06d09735..87692b5aa5bf 100644 --- a/internal/command/views/show.go +++ b/internal/command/views/show.go @@ -83,7 +83,7 @@ func (v *ShowHuman) Display(config *configs.Config, plan *plans.Plan, planJSON * OutputChanges: outputs, ResourceChanges: changed, ResourceDrift: drift, - ProviderSchemas: jsonprovider.MarshalForRenderer(schemas), + ProviderSchemas: jsonprovider.MarshalForRenderer(schemas, false), RelevantAttributes: attrs, } @@ -112,7 +112,7 @@ func (v *ShowHuman) Display(config *configs.Config, plan *plans.Plan, planJSON * ProviderFormatVersion: jsonprovider.FormatVersion, RootModule: root, RootModuleOutputs: outputs, - ProviderSchemas: jsonprovider.MarshalForRenderer(schemas), + ProviderSchemas: jsonprovider.MarshalForRenderer(schemas, false), } renderer.RenderHumanState(jstate) diff --git a/internal/command/views/test.go b/internal/command/views/test.go index 6f8135c2e063..e4a5b0acd847 100644 --- a/internal/command/views/test.go +++ b/internal/command/views/test.go @@ -199,7 +199,7 @@ func (t *TestHuman) Run(run *moduletest.Run, file *moduletest.File, progress mod ProviderFormatVersion: jsonprovider.FormatVersion, RootModule: root, RootModuleOutputs: outputs, - ProviderSchemas: jsonprovider.MarshalForRenderer(schemas), + ProviderSchemas: jsonprovider.MarshalForRenderer(schemas, false), } t.view.streams.Println() // Separate the state from any previous statements. @@ -221,7 +221,7 @@ func (t *TestHuman) Run(run *moduletest.Run, file *moduletest.File, progress mod OutputChanges: outputs, ResourceChanges: changed, ResourceDrift: drift, - ProviderSchemas: jsonprovider.MarshalForRenderer(schemas), + ProviderSchemas: jsonprovider.MarshalForRenderer(schemas, false), RelevantAttributes: attrs, } @@ -560,7 +560,7 @@ func (t *TestJSON) Run(run *moduletest.Run, file *moduletest.File, progress modu ProviderFormatVersion: jsonprovider.FormatVersion, RootModule: root, RootModuleOutputs: outputs, - ProviderSchemas: jsonprovider.MarshalForRenderer(schemas), + ProviderSchemas: jsonprovider.MarshalForRenderer(schemas, false), } t.view.log.Info( @@ -584,7 +584,7 @@ func (t *TestJSON) Run(run *moduletest.Run, file *moduletest.File, progress modu OutputChanges: outputs, ResourceChanges: changed, ResourceDrift: drift, - ProviderSchemas: jsonprovider.MarshalForRenderer(schemas), + ProviderSchemas: jsonprovider.MarshalForRenderer(schemas, false), RelevantAttributes: attrs, }