Include list resource schemas in provider json schemas (TF-25497) (#37163)

* Include list schemas in provider json schemas

* Only include list schemas in experimental builds
This commit is contained in:
Daniel Banck 2025-06-30 10:59:19 +02:00 committed by GitHub
parent 38e2ed42c4
commit ab04e5cfec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 88 additions and 24 deletions

View file

@ -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,

View file

@ -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()

View file

@ -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
}

View file

@ -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},
},
},
},
},
}
}

View file

@ -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.
`

View file

@ -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.`

View file

@ -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,
}

View file

@ -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)

View file

@ -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,
}