terraform: refactor ProvidedBy() to return an addrs.ProviderConfig interface (#24295)
* terraform: refactor ProvidedBy() to return an addrs.ProviderConfig interface This refactor allows terraform to indicate whether a specific provider configuration was found for the resource or if it is instead returning the assumed default. With that additional information the provider transformer can check if there is a specific (non-default) provider FQN.
This commit is contained in:
parent
e6592dc710
commit
6118d22c1f
|
@ -285,25 +285,17 @@ func (n *NodeAbstractResource) SetProvider(p addrs.AbsProviderConfig) {
|
|||
}
|
||||
|
||||
// GraphNodeProviderConsumer
|
||||
func (n *NodeAbstractResource) ProvidedBy() (addrs.AbsProviderConfig, bool) {
|
||||
func (n *NodeAbstractResource) ProvidedBy() (addrs.ProviderConfig, bool) {
|
||||
// If we have a config we prefer that above all else
|
||||
if n.Config != nil {
|
||||
relAddr := n.Config.ProviderConfigAddr()
|
||||
// FIXME: this will need to lookup the provider and see if there's an
|
||||
// FQN associated with the local config
|
||||
fqn := addrs.NewLegacyProvider(relAddr.LocalName)
|
||||
return addrs.AbsProviderConfig{
|
||||
Provider: fqn,
|
||||
Module: n.Path(),
|
||||
Alias: relAddr.Alias,
|
||||
return addrs.LocalProviderConfig{
|
||||
LocalName: relAddr.LocalName,
|
||||
Alias: relAddr.Alias,
|
||||
}, false
|
||||
}
|
||||
|
||||
// Use our type and containing module path to guess a provider configuration address.
|
||||
// FIXME: This is relying on the FQN-to-local matching true only of legacy
|
||||
// addresses, so this will need to switch to using an addrs.LocalProviderConfig
|
||||
// with the local name here, once we've done the work elsewhere to make
|
||||
// that possible.
|
||||
defaultFQN := n.Addr.Resource.DefaultProvider()
|
||||
return addrs.AbsProviderConfig{
|
||||
Provider: defaultFQN,
|
||||
|
@ -312,19 +304,13 @@ func (n *NodeAbstractResource) ProvidedBy() (addrs.AbsProviderConfig, bool) {
|
|||
}
|
||||
|
||||
// GraphNodeProviderConsumer
|
||||
func (n *NodeAbstractResourceInstance) ProvidedBy() (addrs.AbsProviderConfig, bool) {
|
||||
func (n *NodeAbstractResourceInstance) ProvidedBy() (addrs.ProviderConfig, bool) {
|
||||
// If we have a config we prefer that above all else
|
||||
if n.Config != nil {
|
||||
relAddr := n.Config.ProviderConfigAddr()
|
||||
// Use our type and containing module path to guess a provider configuration address.
|
||||
// FIXME: This is relying on the FQN-to-local matching true only of legacy
|
||||
// addresses.
|
||||
fqn := addrs.NewLegacyProvider(relAddr.LocalName)
|
||||
|
||||
return addrs.AbsProviderConfig{
|
||||
Provider: fqn,
|
||||
Module: n.Path(),
|
||||
Alias: relAddr.Alias,
|
||||
return addrs.LocalProviderConfig{
|
||||
LocalName: relAddr.LocalName,
|
||||
Alias: relAddr.Alias,
|
||||
}, false
|
||||
}
|
||||
|
||||
|
@ -337,10 +323,6 @@ func (n *NodeAbstractResourceInstance) ProvidedBy() (addrs.AbsProviderConfig, bo
|
|||
}
|
||||
|
||||
// Use our type and containing module path to guess a provider configuration address
|
||||
// FIXME: This is relying on the FQN-to-local matching true only of legacy
|
||||
// addresses, so this will need to switch to using an addrs.LocalProviderConfig
|
||||
// with the local name here, once we've done the work elsewhere to make
|
||||
// that possible.
|
||||
defaultFQN := n.Addr.Resource.DefaultProvider()
|
||||
return addrs.AbsProviderConfig{
|
||||
Provider: defaultFQN,
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/hashicorp/terraform/addrs"
|
||||
"github.com/hashicorp/terraform/configs/configschema"
|
||||
"github.com/hashicorp/terraform/dag"
|
||||
)
|
||||
|
@ -59,8 +60,17 @@ func (t *AttachSchemaTransformer) Transform(g *Graph) error {
|
|||
mode := addr.Resource.Mode
|
||||
typeName := addr.Resource.Type
|
||||
providerAddr, _ := tv.ProvidedBy()
|
||||
var providerFqn addrs.Provider
|
||||
|
||||
schema, version := t.Schemas.ResourceTypeConfig(providerAddr.Provider, mode, typeName)
|
||||
switch p := providerAddr.(type) {
|
||||
case addrs.LocalProviderConfig:
|
||||
// FIXME: need to look up the providerFQN in the config
|
||||
providerFqn = addrs.NewLegacyProvider(p.LocalName)
|
||||
case addrs.AbsProviderConfig:
|
||||
providerFqn = p.Provider
|
||||
}
|
||||
|
||||
schema, version := t.Schemas.ResourceTypeConfig(providerFqn, mode, typeName)
|
||||
if schema == nil {
|
||||
log.Printf("[ERROR] AttachSchemaTransformer: No resource schema available for %s", addr)
|
||||
continue
|
||||
|
|
|
@ -59,7 +59,7 @@ func (n *graphNodeImportState) Name() string {
|
|||
}
|
||||
|
||||
// GraphNodeProviderConsumer
|
||||
func (n *graphNodeImportState) ProvidedBy() (addrs.AbsProviderConfig, bool) {
|
||||
func (n *graphNodeImportState) ProvidedBy() (addrs.ProviderConfig, bool) {
|
||||
// We assume that n.ProviderAddr has been properly populated here.
|
||||
// It's the responsibility of the code creating a graphNodeImportState
|
||||
// to populate this, possibly by calling DefaultProviderConfig() on the
|
||||
|
|
|
@ -62,11 +62,12 @@ type GraphNodeCloseProvider interface {
|
|||
// or in an ancestor module, with the resulting absolute address passed to
|
||||
// SetProvider.
|
||||
type GraphNodeProviderConsumer interface {
|
||||
GraphNodeSubPath
|
||||
// ProvidedBy returns the address of the provider configuration the node
|
||||
// refers to. If the returned "exact" value is true, this address will
|
||||
// be taken exactly. If "exact" is false, a provider configuration from
|
||||
// an ancestor module may be selected instead.
|
||||
ProvidedBy() (addr addrs.AbsProviderConfig, exact bool)
|
||||
ProvidedBy() (addr addrs.ProviderConfig, exact bool)
|
||||
// Set the resolved provider address for this resource.
|
||||
SetProvider(addrs.AbsProviderConfig)
|
||||
}
|
||||
|
@ -110,20 +111,77 @@ func (t *ProviderTransformer) Transform(g *Graph) error {
|
|||
if pv, ok := v.(GraphNodeProviderConsumer); ok {
|
||||
requested[v] = make(map[string]ProviderRequest)
|
||||
|
||||
p, exact := pv.ProvidedBy()
|
||||
if exact {
|
||||
log.Printf("[TRACE] ProviderTransformer: %s is provided by %s exactly", dag.VertexName(v), p)
|
||||
} else {
|
||||
log.Printf("[TRACE] ProviderTransformer: %s is provided by %s or inherited equivalent", dag.VertexName(v), p)
|
||||
providerAddr, exact := pv.ProvidedBy()
|
||||
var absPc addrs.AbsProviderConfig
|
||||
var providerFqn addrs.Provider
|
||||
|
||||
switch p := providerAddr.(type) {
|
||||
case addrs.AbsProviderConfig:
|
||||
absPc = p
|
||||
// ProvidedBy() returns an AbsProviderConfig + exact == true
|
||||
// when the provider configuration is set in state, so we do not
|
||||
// need to verify the FQN matches.
|
||||
if exact {
|
||||
log.Printf("[TRACE] ProviderTransformer: %s is provided by %s exactly", dag.VertexName(v), absPc)
|
||||
break
|
||||
}
|
||||
|
||||
// if there is no config at all, the assumed default provider
|
||||
// must be correct.
|
||||
if t.Config == nil {
|
||||
break
|
||||
}
|
||||
|
||||
// If `exact` is false, an AbsProviderConfig indicates that
|
||||
// ProvidedBy() returned an inferred default FQN. We must check
|
||||
// if the inferred type name matches a non-default provider
|
||||
// source in the config.
|
||||
modConfig := t.Config.DescendentForInstance(pv.Path())
|
||||
if modConfig != nil {
|
||||
providerFqn = modConfig.Module.ProviderForLocalConfig(addrs.LocalProviderConfig{
|
||||
LocalName: p.Provider.Type,
|
||||
})
|
||||
// This is only a change to the absPc if
|
||||
// ProviderForLocalConfig returns a different Provider
|
||||
absPc.Provider = providerFqn
|
||||
}
|
||||
|
||||
case addrs.LocalProviderConfig:
|
||||
// ProvidedBy() return a LocalProviderConfig when the resource
|
||||
// contains a `provider` attribute
|
||||
modPath := pv.Path()
|
||||
if t.Config == nil {
|
||||
absPc.Provider = addrs.NewLegacyProvider(p.LocalName)
|
||||
absPc.Module = modPath
|
||||
absPc.Alias = p.Alias
|
||||
break
|
||||
}
|
||||
|
||||
modConfig := t.Config.DescendentForInstance(modPath)
|
||||
if modConfig == nil {
|
||||
absPc.Provider = addrs.NewLegacyProvider(p.LocalName)
|
||||
} else {
|
||||
absPc.Provider = modConfig.Module.ProviderForLocalConfig(p)
|
||||
}
|
||||
absPc.Module = modPath
|
||||
absPc.Alias = p.Alias
|
||||
|
||||
default:
|
||||
// This should never happen, the case statements are exhaustive
|
||||
panic(fmt.Sprintf("%s: provider for %s couldn't be determined", dag.VertexName(v), absPc))
|
||||
}
|
||||
|
||||
requested[v][p.String()] = ProviderRequest{
|
||||
Addr: p,
|
||||
if !exact {
|
||||
log.Printf("[TRACE] ProviderTransformer: %s is provided by %s or inherited equivalent", dag.VertexName(v), absPc)
|
||||
}
|
||||
|
||||
requested[v][absPc.String()] = ProviderRequest{
|
||||
Addr: absPc,
|
||||
Exact: exact,
|
||||
}
|
||||
|
||||
// Direct references need the provider configured as well as initialized
|
||||
needConfigured[p.String()] = p
|
||||
needConfigured[absPc.String()] = absPc
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -303,16 +361,26 @@ func (t *MissingProviderTransformer) Transform(g *Graph) error {
|
|||
// the later proper resolution of provider inheritance done by
|
||||
// ProviderTransformer.
|
||||
p, _ := pv.ProvidedBy()
|
||||
if p.Alias != "" {
|
||||
// We do not create default aliased configurations.
|
||||
log.Println("[TRACE] MissingProviderTransformer: skipping implication of aliased config", p)
|
||||
continue
|
||||
var providerFqn addrs.Provider
|
||||
switch p.(type) {
|
||||
case addrs.LocalProviderConfig:
|
||||
if p.(addrs.LocalProviderConfig).Alias != "" {
|
||||
// We do not create default aliased configurations.
|
||||
log.Println("[TRACE] MissingProviderTransformer: skipping implication of aliased config", p)
|
||||
continue
|
||||
}
|
||||
providerFqn = addrs.NewLegacyProvider(p.(addrs.LocalProviderConfig).LocalName)
|
||||
case addrs.AbsProviderConfig:
|
||||
providerFqn = p.(addrs.AbsProviderConfig).Provider
|
||||
default:
|
||||
// This should never happen, the case statements are exhaustive
|
||||
panic(fmt.Sprintf("%s: provider for %s couldn't be determined", dag.VertexName(v), p))
|
||||
}
|
||||
|
||||
// We're going to create an implicit _default_ configuration for the
|
||||
// referenced provider type in the _root_ module, ignoring all other
|
||||
// aspects of the resource's declared provider address.
|
||||
defaultAddr := addrs.RootModuleInstance.ProviderConfigDefault(p.Provider)
|
||||
defaultAddr := addrs.RootModuleInstance.ProviderConfigDefault(providerFqn)
|
||||
key := defaultAddr.String()
|
||||
provider := m[key]
|
||||
|
||||
|
|
Loading…
Reference in New Issue