jsonconfig: fix keys for default providers

Fixes provider config keys to reflect implicit provider inheritance.
This commit is contained in:
nozaq 2022-02-16 01:12:55 +09:00
parent aed7162e9a
commit 7f4019e1f6
No known key found for this signature in database
GPG Key ID: 99A56FF51B467245
6 changed files with 368 additions and 16 deletions

View File

@ -231,9 +231,37 @@ func marshalProviderConfigs(
p.VersionConstraint = getproviders.VersionConstraintsString(vc)
}
if c.Parent != nil {
parentKey := opaqueProviderKey(pr.Name, c.Parent.Path.String())
p.parentKey = findSourceProviderKey(parentKey, m)
}
m[key] = p
}
// In child modules, providers defined in the parent module can be implicitly used.
// Such providers could have no requirements and configuration blocks defined.
if c.Parent != nil {
for req := range reqs {
// Implicit inheritance only applies to the default provider,
// so the provider name must be same as the provider type.
key := opaqueProviderKey(req.Type, c.Path.String())
if _, exists := m[key]; exists {
continue
}
parentKey := opaqueProviderKey(req.Type, c.Parent.Path.String())
p := providerConfig{
Name: req.Type,
FullName: req.String(),
ModuleAddress: c.Path.String(),
parentKey: findSourceProviderKey(parentKey, m),
}
m[key] = p
}
}
// Must also visit our child modules, recursively.
for name, mc := range c.Module.ModuleCalls {
// Keys in c.Children are guaranteed to match those in c.Module.ModuleCalls
@ -259,22 +287,7 @@ func marshalProviderConfigs(
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
}
}
p.parentKey = findSourceProviderKey(parentKey, m)
m[key] = p
}
@ -527,3 +540,20 @@ func opaqueProviderKey(provider string, addr string) (key string) {
}
return key
}
// 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
func findSourceProviderKey(startKey string, m map[string]providerConfig) string {
parentKey := startKey
for {
parent, exists := m[parentKey]
if !exists || parent.parentKey == "" {
break
}
parentKey = parent.parentKey
}
return parentKey
}

View File

@ -0,0 +1,19 @@
terraform {
required_providers {
test = {
source = "hashicorp/test"
}
}
}
resource "test_instance" "test" {
ami = "bar"
}
module "with_requirement" {
source = "./nested"
}
module "no_requirements" {
source = "./nested-no-requirements"
}

View File

@ -0,0 +1,3 @@
resource "test_instance" "test" {
ami = "qux"
}

View File

@ -0,0 +1,11 @@
terraform {
required_providers {
test = {
source = "hashicorp/test"
}
}
}
resource "test_instance" "test" {
ami = "baz"
}

View File

@ -0,0 +1,19 @@
provider "test" {
region = "somewhere"
}
provider "test" {
alias = "backup"
region = "elsewhere"
}
resource "test_instance" "test" {
ami = "foo"
}
module "child" {
source = "./child"
providers = {
test = test.backup
}
}

View File

@ -0,0 +1,270 @@
{
"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": {}
}
],
"child_modules": [
{
"resources": [
{
"address": "module.child.test_instance.test",
"mode": "managed",
"type": "test_instance",
"name": "test",
"provider_name": "registry.terraform.io/hashicorp/test",
"schema_version": 0,
"values": {
"ami": "bar"
},
"sensitive_values": {}
}
],
"address": "module.child",
"child_modules": [
{
"resources": [
{
"address": "module.child.module.with_requirement.test_instance.test",
"mode": "managed",
"type": "test_instance",
"name": "test",
"provider_name": "registry.terraform.io/hashicorp/test",
"schema_version": 0,
"values": {
"ami": "baz"
},
"sensitive_values": {}
}
],
"address": "module.child.module.with_requirement"
},
{
"resources": [
{
"address": "module.child.module.no_requirements.test_instance.test",
"mode": "managed",
"type": "test_instance",
"name": "test",
"provider_name": "registry.terraform.io/hashicorp/test",
"schema_version": 0,
"values": {
"ami": "qux"
},
"sensitive_values": {}
}
],
"address": "module.child.module.no_requirements"
}
]
}
]
}
},
"resource_changes": [
{
"address": "module.child.module.no_requirements.test_instance.test",
"module_address": "module.child.module.no_requirements",
"mode": "managed",
"type": "test_instance",
"name": "test",
"provider_name": "registry.terraform.io/hashicorp/test",
"change": {
"actions": [
"create"
],
"before": null,
"after": {
"ami": "qux"
},
"after_unknown": {
"id": true
},
"before_sensitive": false,
"after_sensitive": {}
}
},
{
"address": "module.child.module.with_requirement.test_instance.test",
"module_address": "module.child.module.with_requirement",
"mode": "managed",
"type": "test_instance",
"name": "test",
"provider_name": "registry.terraform.io/hashicorp/test",
"change": {
"actions": [
"create"
],
"before": null,
"after": {
"ami": "baz"
},
"after_unknown": {
"id": true
},
"before_sensitive": false,
"after_sensitive": {}
}
},
{
"address": "module.child.test_instance.test",
"module_address": "module.child",
"mode": "managed",
"type": "test_instance",
"name": "test",
"provider_name": "registry.terraform.io/hashicorp/test",
"change": {
"actions": [
"create"
],
"before": null,
"after": {
"ami": "bar"
},
"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": {}
}
}
],
"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
}
],
"module_calls": {
"child": {
"source": "./child",
"module": {
"resources": [
{
"address": "test_instance.test",
"mode": "managed",
"type": "test_instance",
"name": "test",
"provider_config_key": "test.backup",
"expressions": {
"ami": {
"constant_value": "bar"
}
},
"schema_version": 0
}
],
"module_calls": {
"no_requirements": {
"source": "./nested-no-requirements",
"module": {
"resources": [
{
"address": "test_instance.test",
"mode": "managed",
"type": "test_instance",
"name": "test",
"provider_config_key": "test.backup",
"expressions": {
"ami": {
"constant_value": "qux"
}
},
"schema_version": 0
}
]
}
},
"with_requirement": {
"source": "./nested",
"module": {
"resources": [
{
"address": "test_instance.test",
"mode": "managed",
"type": "test_instance",
"name": "test",
"provider_config_key": "test.backup",
"expressions": {
"ami": {
"constant_value": "baz"
}
},
"schema_version": 0
}
]
}
}
}
}
}
}
}
}
}