diff --git a/internal/command/jsonconfig/config.go b/internal/command/jsonconfig/config.go index 617181ba608b..807444d6e4f1 100644 --- a/internal/command/jsonconfig/config.go +++ b/internal/command/jsonconfig/config.go @@ -27,10 +27,12 @@ type config struct { // module boundaries. type providerConfig struct { Name string `json:"name,omitempty"` + FullName string `json:"full_name,omitempty"` Alias string `json:"alias,omitempty"` VersionConstraint string `json:"version_constraint,omitempty"` ModuleAddress string `json:"module_address,omitempty"` Expressions map[string]interface{} `json:"expressions,omitempty"` + parentKey string } type module struct { @@ -120,7 +122,6 @@ func Marshal(c *configs.Config, schemas *terraform.Schemas) ([]byte, error) { pcs := make(map[string]providerConfig) marshalProviderConfigs(c, schemas, pcs) - output.ProviderConfigs = pcs rootModule, err := marshalModule(c, schemas, "") if err != nil { @@ -128,6 +129,15 @@ func Marshal(c *configs.Config, schemas *terraform.Schemas) ([]byte, error) { } output.RootModule = rootModule + normalizeModuleProviderKeys(&rootModule, pcs) + + for name, pc := range pcs { + if pc.parentKey != "" { + delete(pcs, name) + } + } + output.ProviderConfigs = pcs + ret, err := json.Marshal(output) return ret, err } @@ -154,6 +164,7 @@ func marshalProviderConfigs( p := providerConfig{ Name: pc.Name, + FullName: providerFqn.String(), Alias: pc.Alias, ModuleAddress: c.Path.String(), Expressions: marshalExpressions(pc.Config, schema), @@ -176,6 +187,30 @@ func marshalProviderConfigs( // Ensure that any required providers with no associated configuration // block are included in the set. for k, pr := range c.Module.ProviderRequirements.RequiredProviders { + // If a provider has aliases defined, process those first. + for _, alias := range pr.Aliases { + // If there exists a value for this provider, we have nothing to add + // to it, so skip. + key := opaqueProviderKey(alias.StringCompact(), c.Path.String()) + if _, exists := m[key]; exists { + continue + } + // Given no provider configuration block exists, the only fields we can + // fill here are the local name, FQN, module address, and version + // constraints. + p := providerConfig{ + Name: pr.Name, + FullName: pr.Type.String(), + ModuleAddress: c.Path.String(), + } + + if vc, ok := reqs[pr.Type]; ok { + p.VersionConstraint = getproviders.VersionConstraintsString(vc) + } + + m[key] = p + } + // If there exists a value for this provider, we have nothing to add // to it, so skip. key := opaqueProviderKey(k, c.Path.String()) @@ -188,6 +223,7 @@ func marshalProviderConfigs( // constraints. p := providerConfig{ Name: pr.Name, + FullName: pr.Type.String(), ModuleAddress: c.Path.String(), } @@ -199,7 +235,53 @@ func marshalProviderConfigs( } // Must also visit our child modules, recursively. - for _, cc := range c.Children { + for name, mc := range c.Module.ModuleCalls { + // Keys in c.Children are guaranteed to match those in c.Module.ModuleCalls + cc := c.Children[name] + + // Add provider config map entries for passed provider configs, + // pointing at the passed configuration + for _, ppc := range mc.Providers { + // These provider names include aliases, if set + moduleProviderName := ppc.InChild.String() + parentProviderName := ppc.InParent.String() + + // Look up the provider FQN from the module context, using the non-aliased local name + providerFqn := cc.ProviderForConfigAddr(addrs.LocalProviderConfig{LocalName: ppc.InChild.Name}) + + // The presence of passed provider configs means that we cannot have + // any configuration expressions or version constraints here + p := providerConfig{ + Name: moduleProviderName, + FullName: providerFqn.String(), + ModuleAddress: cc.Path.String(), + } + + key := opaqueProviderKey(moduleProviderName, cc.Path.String()) + parentKey := opaqueProviderKey(parentProviderName, cc.Parent.Path.String()) + + // Traverse up the module call tree until we find the provider + // configuration which has no linked parent config. This is then + // the source of the configuration used in this module call, so + // we link to it directly + for { + parent, exists := m[parentKey] + if !exists { + break + } + p.parentKey = parentKey + parentKey = parent.parentKey + if parentKey == "" { + break + } + } + + m[key] = p + } + + // Finally, marshal any other provider configs within the called module. + // It is safe to do this last because it is invalid to configure a + // provider which has passed provider configs in the module call. marshalProviderConfigs(cc, schemas, m) } } @@ -319,7 +401,9 @@ func marshalModuleCall(c *configs.Config, mc *configs.ModuleCall, schemas *terra } ret.Expressions = marshalExpressions(mc.Config, schema) - module, _ := marshalModule(c, schemas, mc.Name) + + module, _ := marshalModule(c, schemas, c.Path.String()) + ret.Module = module if len(mc.DependsOn) > 0 { @@ -342,11 +426,12 @@ func marshalModuleCall(c *configs.Config, mc *configs.ModuleCall, schemas *terra func marshalResources(resources map[string]*configs.Resource, schemas *terraform.Schemas, moduleAddr string) ([]resource, error) { var rs []resource for _, v := range resources { + providerConfigKey := opaqueProviderKey(v.ProviderConfigAddr().StringCompact(), moduleAddr) r := resource{ Address: v.Addr().String(), Type: v.Type, Name: v.Name, - ProviderConfigKey: opaqueProviderKey(v.ProviderConfigAddr().StringCompact(), moduleAddr), + ProviderConfigKey: providerConfigKey, } switch v.Mode { @@ -416,6 +501,23 @@ func marshalResources(resources map[string]*configs.Resource, schemas *terraform return rs, nil } +// Flatten all resource provider keys in a module and its descendents, such +// that any resources from providers using a configuration passed through the +// module call have a direct refernce to that provider configuration. +func normalizeModuleProviderKeys(m *module, pcs map[string]providerConfig) { + for i, r := range m.Resources { + if pc, exists := pcs[r.ProviderConfigKey]; exists { + if _, hasParent := pcs[pc.parentKey]; hasParent { + m.Resources[i].ProviderConfigKey = pc.parentKey + } + } + } + + for _, mc := range m.ModuleCalls { + normalizeModuleProviderKeys(&mc.Module, pcs) + } +} + // opaqueProviderKey generates a unique absProviderConfig-like string from the module // address and provider func opaqueProviderKey(provider string, addr string) (key string) { diff --git a/internal/command/jsonplan/plan.go b/internal/command/jsonplan/plan.go index 06ed97961012..53fe8ec01b45 100644 --- a/internal/command/jsonplan/plan.go +++ b/internal/command/jsonplan/plan.go @@ -22,7 +22,7 @@ import ( // FormatVersion represents the version of the json format and will be // incremented for any change to this format that requires changes to a // consuming parser. -const FormatVersion = "1.0" +const FormatVersion = "1.1" // Plan is the top-level representation of the json format of a plan. It includes // the complete config and current state. diff --git a/internal/command/show_test.go b/internal/command/show_test.go index 5f220e906ee0..00a9e555a2e5 100644 --- a/internal/command/show_test.go +++ b/internal/command/show_test.go @@ -576,6 +576,9 @@ func TestShow_json_output(t *testing.T) { } json.Unmarshal([]byte(byteValue), &want) + // Disregard format version to reduce needless test fixture churn + want.FormatVersion = got.FormatVersion + if !cmp.Equal(got, want) { t.Fatalf("wrong result:\n %v\n", cmp.Diff(got, want)) } @@ -667,6 +670,9 @@ func TestShow_json_output_sensitive(t *testing.T) { } json.Unmarshal([]byte(byteValue), &want) + // Disregard format version to reduce needless test fixture churn + want.FormatVersion = got.FormatVersion + if !cmp.Equal(got, want) { t.Fatalf("wrong result:\n %v\n", cmp.Diff(got, want)) } diff --git a/internal/command/testdata/show-json-sensitive/output.json b/internal/command/testdata/show-json-sensitive/output.json index 206fbb7f6e60..9d1ec24bc800 100644 --- a/internal/command/testdata/show-json-sensitive/output.json +++ b/internal/command/testdata/show-json-sensitive/output.json @@ -164,6 +164,7 @@ "provider_config": { "test": { "name": "test", + "full_name": "registry.terraform.io/hashicorp/test", "expressions": { "region": { "constant_value": "somewhere" diff --git a/internal/command/testdata/show-json/basic-create/output.json b/internal/command/testdata/show-json/basic-create/output.json index d1b8aae5361b..83c14458066c 100644 --- a/internal/command/testdata/show-json/basic-create/output.json +++ b/internal/command/testdata/show-json/basic-create/output.json @@ -152,6 +152,7 @@ "provider_config": { "test": { "name": "test", + "full_name": "registry.terraform.io/hashicorp/test", "expressions": { "region": { "constant_value": "somewhere" diff --git a/internal/command/testdata/show-json/modules/output.json b/internal/command/testdata/show-json/modules/output.json index 4ed0ea45d692..1728282592de 100644 --- a/internal/command/testdata/show-json/modules/output.json +++ b/internal/command/testdata/show-json/modules/output.json @@ -224,7 +224,7 @@ "mode": "managed", "type": "test_instance", "name": "test", - "provider_config_key": "module_test_bar:test", + "provider_config_key": "module.module_test_bar:test", "expressions": { "ami": { "references": [ @@ -265,7 +265,7 @@ "mode": "managed", "type": "test_instance", "name": "test", - "provider_config_key": "module_test_foo:test", + "provider_config_key": "module.module_test_foo:test", "expressions": { "ami": { "references": [ @@ -291,7 +291,8 @@ "provider_config": { "module.module_test_foo:test": { "module_address": "module.module_test_foo", - "name": "test" + "name": "test", + "full_name": "registry.terraform.io/hashicorp/test" } } } diff --git a/internal/command/testdata/show-json/nested-modules/output.json b/internal/command/testdata/show-json/nested-modules/output.json index 359ea9ae181c..6d0af8a1468c 100644 --- a/internal/command/testdata/show-json/nested-modules/output.json +++ b/internal/command/testdata/show-json/nested-modules/output.json @@ -68,7 +68,7 @@ "mode": "managed", "type": "test_instance", "name": "test", - "provider_config_key": "more:test", + "provider_config_key": "module.my_module.module.more:test", "expressions": { "ami": { "references": [ diff --git a/internal/command/testdata/show-json/provider-aliasing/child/main.tf b/internal/command/testdata/show-json/provider-aliasing/child/main.tf new file mode 100644 index 000000000000..42555752cfd1 --- /dev/null +++ b/internal/command/testdata/show-json/provider-aliasing/child/main.tf @@ -0,0 +1,26 @@ +terraform { + required_providers { + test = { + source = "hashicorp/test" + configuration_aliases = [test, test.second] + } + } +} + +resource "test_instance" "test_primary" { + ami = "primary" + provider = test +} + +resource "test_instance" "test_secondary" { + ami = "secondary" + provider = test.second +} + +module "grandchild" { + source = "./nested" + providers = { + test = test + test.alt = test.second + } +} diff --git a/internal/command/testdata/show-json/provider-aliasing/child/nested/main.tf b/internal/command/testdata/show-json/provider-aliasing/child/nested/main.tf new file mode 100644 index 000000000000..ff1fe9a1afba --- /dev/null +++ b/internal/command/testdata/show-json/provider-aliasing/child/nested/main.tf @@ -0,0 +1,18 @@ +terraform { + required_providers { + test = { + source = "hashicorp/test" + configuration_aliases = [test, test.alt] + } + } +} + +resource "test_instance" "test_main" { + ami = "main" + provider = test +} + +resource "test_instance" "test_alternate" { + ami = "secondary" + provider = test.alt +} diff --git a/internal/command/testdata/show-json/provider-aliasing/main.tf b/internal/command/testdata/show-json/provider-aliasing/main.tf new file mode 100644 index 000000000000..7f6b0a3e337a --- /dev/null +++ b/internal/command/testdata/show-json/provider-aliasing/main.tf @@ -0,0 +1,34 @@ +provider "test" { + region = "somewhere" +} + +provider "test" { + alias = "backup" + region = "elsewhere" +} + +resource "test_instance" "test" { + ami = "foo" + provider = test +} + +resource "test_instance" "test_backup" { + ami = "foo-backup" + provider = test.backup +} + +module "child" { + source = "./child" + providers = { + test = test + test.second = test.backup + } +} + +module "sibling" { + source = "./child" + providers = { + test = test + test.second = test + } +} diff --git a/internal/command/testdata/show-json/provider-aliasing/output.json b/internal/command/testdata/show-json/provider-aliasing/output.json new file mode 100755 index 000000000000..187141c9cf88 --- /dev/null +++ b/internal/command/testdata/show-json/provider-aliasing/output.json @@ -0,0 +1,567 @@ +{ + "format_version": "1.0", + "terraform_version": "1.1.0-dev", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "test_instance.test", + "mode": "managed", + "type": "test_instance", + "name": "test", + "provider_name": "registry.terraform.io/hashicorp/test", + "schema_version": 0, + "values": { + "ami": "foo" + }, + "sensitive_values": {} + }, + { + "address": "test_instance.test_backup", + "mode": "managed", + "type": "test_instance", + "name": "test_backup", + "provider_name": "registry.terraform.io/hashicorp/test", + "schema_version": 0, + "values": { + "ami": "foo-backup" + }, + "sensitive_values": {} + } + ], + "child_modules": [ + { + "resources": [ + { + "address": "module.child.test_instance.test_primary", + "mode": "managed", + "type": "test_instance", + "name": "test_primary", + "provider_name": "registry.terraform.io/hashicorp/test", + "schema_version": 0, + "values": { + "ami": "primary" + }, + "sensitive_values": {} + }, + { + "address": "module.child.test_instance.test_secondary", + "mode": "managed", + "type": "test_instance", + "name": "test_secondary", + "provider_name": "registry.terraform.io/hashicorp/test", + "schema_version": 0, + "values": { + "ami": "secondary" + }, + "sensitive_values": {} + } + ], + "address": "module.child", + "child_modules": [ + { + "resources": [ + { + "address": "module.child.module.grandchild.test_instance.test_alternate", + "mode": "managed", + "type": "test_instance", + "name": "test_alternate", + "provider_name": "registry.terraform.io/hashicorp/test", + "schema_version": 0, + "values": { + "ami": "secondary" + }, + "sensitive_values": {} + }, + { + "address": "module.child.module.grandchild.test_instance.test_main", + "mode": "managed", + "type": "test_instance", + "name": "test_main", + "provider_name": "registry.terraform.io/hashicorp/test", + "schema_version": 0, + "values": { + "ami": "main" + }, + "sensitive_values": {} + } + ], + "address": "module.child.module.grandchild" + } + ] + }, + { + "resources": [ + { + "address": "module.sibling.test_instance.test_primary", + "mode": "managed", + "type": "test_instance", + "name": "test_primary", + "provider_name": "registry.terraform.io/hashicorp/test", + "schema_version": 0, + "values": { + "ami": "primary" + }, + "sensitive_values": {} + }, + { + "address": "module.sibling.test_instance.test_secondary", + "mode": "managed", + "type": "test_instance", + "name": "test_secondary", + "provider_name": "registry.terraform.io/hashicorp/test", + "schema_version": 0, + "values": { + "ami": "secondary" + }, + "sensitive_values": {} + } + ], + "address": "module.sibling", + "child_modules": [ + { + "resources": [ + { + "address": "module.sibling.module.grandchild.test_instance.test_alternate", + "mode": "managed", + "type": "test_instance", + "name": "test_alternate", + "provider_name": "registry.terraform.io/hashicorp/test", + "schema_version": 0, + "values": { + "ami": "secondary" + }, + "sensitive_values": {} + }, + { + "address": "module.sibling.module.grandchild.test_instance.test_main", + "mode": "managed", + "type": "test_instance", + "name": "test_main", + "provider_name": "registry.terraform.io/hashicorp/test", + "schema_version": 0, + "values": { + "ami": "main" + }, + "sensitive_values": {} + } + ], + "address": "module.sibling.module.grandchild" + } + ] + } + ] + } + }, + "resource_changes": [ + { + "address": "module.child.module.grandchild.test_instance.test_alternate", + "module_address": "module.child.module.grandchild", + "mode": "managed", + "type": "test_instance", + "name": "test_alternate", + "provider_name": "registry.terraform.io/hashicorp/test", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "secondary" + }, + "after_unknown": { + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "module.child.module.grandchild.test_instance.test_main", + "module_address": "module.child.module.grandchild", + "mode": "managed", + "type": "test_instance", + "name": "test_main", + "provider_name": "registry.terraform.io/hashicorp/test", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "main" + }, + "after_unknown": { + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "module.child.test_instance.test_primary", + "module_address": "module.child", + "mode": "managed", + "type": "test_instance", + "name": "test_primary", + "provider_name": "registry.terraform.io/hashicorp/test", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "primary" + }, + "after_unknown": { + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "module.child.test_instance.test_secondary", + "module_address": "module.child", + "mode": "managed", + "type": "test_instance", + "name": "test_secondary", + "provider_name": "registry.terraform.io/hashicorp/test", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "secondary" + }, + "after_unknown": { + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "module.sibling.module.grandchild.test_instance.test_alternate", + "module_address": "module.sibling.module.grandchild", + "mode": "managed", + "type": "test_instance", + "name": "test_alternate", + "provider_name": "registry.terraform.io/hashicorp/test", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "secondary" + }, + "after_unknown": { + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "module.sibling.module.grandchild.test_instance.test_main", + "module_address": "module.sibling.module.grandchild", + "mode": "managed", + "type": "test_instance", + "name": "test_main", + "provider_name": "registry.terraform.io/hashicorp/test", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "main" + }, + "after_unknown": { + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "module.sibling.test_instance.test_primary", + "module_address": "module.sibling", + "mode": "managed", + "type": "test_instance", + "name": "test_primary", + "provider_name": "registry.terraform.io/hashicorp/test", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "primary" + }, + "after_unknown": { + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "module.sibling.test_instance.test_secondary", + "module_address": "module.sibling", + "mode": "managed", + "type": "test_instance", + "name": "test_secondary", + "provider_name": "registry.terraform.io/hashicorp/test", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "secondary" + }, + "after_unknown": { + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "test_instance.test", + "mode": "managed", + "type": "test_instance", + "name": "test", + "provider_name": "registry.terraform.io/hashicorp/test", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "foo" + }, + "after_unknown": { + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "test_instance.test_backup", + "mode": "managed", + "type": "test_instance", + "name": "test_backup", + "provider_name": "registry.terraform.io/hashicorp/test", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "foo-backup" + }, + "after_unknown": { + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + } + ], + "configuration": { + "provider_config": { + "test": { + "name": "test", + "full_name": "registry.terraform.io/hashicorp/test", + "expressions": { + "region": { + "constant_value": "somewhere" + } + } + }, + "test.backup": { + "name": "test", + "full_name": "registry.terraform.io/hashicorp/test", + "alias": "backup", + "expressions": { + "region": { + "constant_value": "elsewhere" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "test_instance.test", + "mode": "managed", + "type": "test_instance", + "name": "test", + "provider_config_key": "test", + "expressions": { + "ami": { + "constant_value": "foo" + } + }, + "schema_version": 0 + }, + { + "address": "test_instance.test_backup", + "mode": "managed", + "type": "test_instance", + "name": "test_backup", + "provider_config_key": "test.backup", + "expressions": { + "ami": { + "constant_value": "foo-backup" + } + }, + "schema_version": 0 + } + ], + "module_calls": { + "child": { + "source": "./child", + "module": { + "resources": [ + { + "address": "test_instance.test_primary", + "mode": "managed", + "type": "test_instance", + "name": "test_primary", + "provider_config_key": "test", + "expressions": { + "ami": { + "constant_value": "primary" + } + }, + "schema_version": 0 + }, + { + "address": "test_instance.test_secondary", + "mode": "managed", + "type": "test_instance", + "name": "test_secondary", + "provider_config_key": "test.backup", + "expressions": { + "ami": { + "constant_value": "secondary" + } + }, + "schema_version": 0 + } + ], + "module_calls": { + "grandchild": { + "source": "./nested", + "module": { + "resources": [ + { + "address": "test_instance.test_alternate", + "mode": "managed", + "type": "test_instance", + "name": "test_alternate", + "provider_config_key": "test.backup", + "expressions": { + "ami": { + "constant_value": "secondary" + } + }, + "schema_version": 0 + }, + { + "address": "test_instance.test_main", + "mode": "managed", + "type": "test_instance", + "name": "test_main", + "provider_config_key": "test", + "expressions": { + "ami": { + "constant_value": "main" + } + }, + "schema_version": 0 + } + ] + } + } + } + } + }, + "sibling": { + "source": "./child", + "module": { + "resources": [ + { + "address": "test_instance.test_primary", + "mode": "managed", + "type": "test_instance", + "name": "test_primary", + "provider_config_key": "test", + "expressions": { + "ami": { + "constant_value": "primary" + } + }, + "schema_version": 0 + }, + { + "address": "test_instance.test_secondary", + "mode": "managed", + "type": "test_instance", + "name": "test_secondary", + "provider_config_key": "test", + "expressions": { + "ami": { + "constant_value": "secondary" + } + }, + "schema_version": 0 + } + ], + "module_calls": { + "grandchild": { + "source": "./nested", + "module": { + "resources": [ + { + "address": "test_instance.test_alternate", + "mode": "managed", + "type": "test_instance", + "name": "test_alternate", + "provider_config_key": "test", + "expressions": { + "ami": { + "constant_value": "secondary" + } + }, + "schema_version": 0 + }, + { + "address": "test_instance.test_main", + "mode": "managed", + "type": "test_instance", + "name": "test_main", + "provider_config_key": "test", + "expressions": { + "ami": { + "constant_value": "main" + } + }, + "schema_version": 0 + } + ] + } + } + } + } + } + } + } + } +} diff --git a/internal/command/testdata/show-json/provider-version-no-config/output.json b/internal/command/testdata/show-json/provider-version-no-config/output.json index 6a8b1f451dc0..b5e78402d8b6 100644 --- a/internal/command/testdata/show-json/provider-version-no-config/output.json +++ b/internal/command/testdata/show-json/provider-version-no-config/output.json @@ -152,6 +152,7 @@ "provider_config": { "test": { "name": "test", + "full_name": "registry.terraform.io/hashicorp/test", "version_constraint": ">= 1.2.3" } }, diff --git a/internal/command/testdata/show-json/provider-version/output.json b/internal/command/testdata/show-json/provider-version/output.json index 11fd3bd64c15..4d86a29b05ca 100644 --- a/internal/command/testdata/show-json/provider-version/output.json +++ b/internal/command/testdata/show-json/provider-version/output.json @@ -152,6 +152,7 @@ "provider_config": { "test": { "name": "test", + "full_name": "registry.terraform.io/hashicorp/test", "expressions": { "region": { "constant_value": "somewhere" diff --git a/website/docs/internals/json-format.mdx b/website/docs/internals/json-format.mdx index 556d442eeb36..9d76f4c7473c 100644 --- a/website/docs/internals/json-format.mdx +++ b/website/docs/internals/json-format.mdx @@ -323,7 +323,7 @@ Because the configuration models are produced at a stage prior to expression eva // the configuration tree, flattened into a single map for convenience since // provider configurations are the one concept in Terraform that can span // across module boundaries. - "provider_configs": { + "provider_config": { // Keys in the provider_configs map are to be considered opaque by callers, // and used just for lookups using the "provider_config_key" property in each @@ -333,6 +333,9 @@ Because the configuration models are produced at a stage prior to expression eva // "name" is the name of the provider without any alias "name": "aws", + // "full_name" is the fully-qualified provider name + "full_name": "registry.terraform.io/hashicorp/aws", + // "alias" is the alias set for a non-default configuration, or unset for // a default configuration. "alias": "foo", @@ -378,7 +381,9 @@ Because the configuration models are produced at a stage prior to expression eva // "provider_config_key" is the key into "provider_configs" (shown // above) for the provider configuration that this resource is - // associated with. + // associated with. If the provider configuration was passed into + // this module from the parent module, the key will point to the + // original provider config block. "provider_config_key": "opaque_provider_ref_aws", // "provisioners" is an optional field which describes any provisioners. @@ -440,7 +445,7 @@ Because the configuration models are produced at a stage prior to expression eva // "module" is a representation of the configuration of the child module // itself, using the same structure as the "root_module" object, // recursively describing the full module tree. - "module": , + "module": } } }