mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
complete passing providers through modules
Here we complete the passing of providers between modules via the module/providers configuration, add another test and update broken test outputs. The DisbableProviderTransformer is being removed, since it was really only for provider configuration inheritance. Since configuration is no longer inherited, there's no need to keep around unused providers. The actually shouldn't be any unused providers going into the graph any longer, but put off verifying that condition for later. Replace it's usage with the PruneProviderTransformer, and use that to also remove the unneeded proxy provider nodes.
This commit is contained in:
parent
49e6ecfd7a
commit
b9b4912bfb
@ -0,0 +1,7 @@
|
||||
provider "aws" {
|
||||
alias = "baz"
|
||||
}
|
||||
|
||||
resource "aws_instance" "baz" {
|
||||
provider = "aws.baz"
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
provider "aws" {
|
||||
alias = "bar"
|
||||
}
|
||||
|
||||
module "grandchild" {
|
||||
source = "./grandchild"
|
||||
providers = {
|
||||
"aws.baz" = "aws.bar"
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
provider "aws" {
|
||||
alias = "foo"
|
||||
value = "config"
|
||||
}
|
||||
|
||||
module "child" {
|
||||
source = "child"
|
||||
providers = {
|
||||
"aws.bar" = "aws.foo"
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
provider "aws" {
|
||||
alias = "bar"
|
||||
}
|
||||
|
||||
resource "aws_instance" "thing" {
|
||||
provider = "aws.bar"
|
||||
}
|
11
terraform/test-fixtures/transform-provider-inherit/main.tf
Normal file
11
terraform/test-fixtures/transform-provider-inherit/main.tf
Normal file
@ -0,0 +1,11 @@
|
||||
provider "aws" {
|
||||
alias = "foo"
|
||||
value = "config"
|
||||
}
|
||||
|
||||
module "child" {
|
||||
source = "child"
|
||||
providers = {
|
||||
"aws.bar" = "aws.foo"
|
||||
}
|
||||
}
|
@ -27,8 +27,8 @@ func TransformProviders(providers []string, concrete ConcreteProviderNodeFunc, m
|
||||
},
|
||||
// Connect the providers
|
||||
&ProviderTransformer{},
|
||||
// Disable unused providers
|
||||
&DisableProviderTransformer{},
|
||||
// Remove unused providers and proxies
|
||||
&PruneProviderTransformer{},
|
||||
// Connect provider to their parent provider nodes
|
||||
&ParentProviderTransformer{},
|
||||
)
|
||||
@ -108,8 +108,8 @@ func (t *ProviderTransformer) Transform(g *Graph) error {
|
||||
// see if this in an inherited provider
|
||||
if p, ok := target.(*graphNodeProxyProvider); ok {
|
||||
g.Remove(p)
|
||||
target = p.Target
|
||||
key = p.Target.Name()
|
||||
target = p.Target()
|
||||
key = target.(GraphNodeProvider).Name()
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] resource %s using provider %s", dag.VertexName(pv), key)
|
||||
@ -253,22 +253,29 @@ func (t *ParentProviderTransformer) Transform(g *Graph) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// PruneProviderTransformer is a GraphTransformer that prunes all the
|
||||
// providers that aren't needed from the graph. A provider is unneeded if
|
||||
// no resource or module is using that provider.
|
||||
// PruneProviderTransformer removes any providers that are not actually used by
|
||||
// anything, and provider proxies. This avoids the provider being initialized
|
||||
// and configured. This both saves resources but also avoids errors since
|
||||
// configuration may imply initialization which may require auth.
|
||||
type PruneProviderTransformer struct{}
|
||||
|
||||
func (t *PruneProviderTransformer) Transform(g *Graph) error {
|
||||
for _, v := range g.Vertices() {
|
||||
// We only care about the providers
|
||||
if pn, ok := v.(GraphNodeProvider); !ok || pn.ProviderName() == "" {
|
||||
// We only care about providers
|
||||
pn, ok := v.(GraphNodeProvider)
|
||||
if !ok || pn.ProviderName() == "" {
|
||||
continue
|
||||
}
|
||||
// Does anything depend on this? If not, then prune it.
|
||||
if s := g.UpEdges(v); s.Len() == 0 {
|
||||
if nv, ok := v.(dag.NamedVertex); ok {
|
||||
log.Printf("[DEBUG] Pruning provider with no dependencies: %s", nv.Name())
|
||||
}
|
||||
|
||||
// ProxyProviders will have up edges, but we're now done with them in the graph
|
||||
if _, ok := v.(*graphNodeProxyProvider); ok {
|
||||
log.Printf("[DEBUG] pruning proxy provider %s", dag.VertexName(v))
|
||||
g.Remove(v)
|
||||
}
|
||||
|
||||
// Remove providers with no dependencies.
|
||||
if g.UpEdges(v).Len() == 0 {
|
||||
log.Printf("[DEBUG] pruning unused provider %s", dag.VertexName(v))
|
||||
g.Remove(v)
|
||||
}
|
||||
}
|
||||
@ -360,17 +367,27 @@ func (n *graphNodeCloseProvider) RemoveIfNotTargeted() bool {
|
||||
// configurations, and are removed after all the resources have been connected
|
||||
// to their providers.
|
||||
type graphNodeProxyProvider struct {
|
||||
NameValue string
|
||||
Path []string
|
||||
Target GraphNodeProvider
|
||||
nameValue string
|
||||
path []string
|
||||
target GraphNodeProvider
|
||||
}
|
||||
|
||||
func (n *graphNodeProxyProvider) ProviderName() string {
|
||||
return n.Target.ProviderName()
|
||||
return n.Target().ProviderName()
|
||||
}
|
||||
|
||||
func (n *graphNodeProxyProvider) Name() string {
|
||||
return ResolveProviderName(n.NameValue, n.Path)
|
||||
return ResolveProviderName(n.nameValue, n.path)
|
||||
}
|
||||
|
||||
// find the concrete provider instance
|
||||
func (n *graphNodeProxyProvider) Target() GraphNodeProvider {
|
||||
switch t := n.target.(type) {
|
||||
case *graphNodeProxyProvider:
|
||||
return t.Target()
|
||||
default:
|
||||
return n.target
|
||||
}
|
||||
}
|
||||
|
||||
// ProviderConfigTransformer adds all provider nodes from the configuration and
|
||||
@ -511,14 +528,14 @@ func (t *ProviderConfigTransformer) addProxyProvider(g *Graph, m *module.Tree, p
|
||||
}
|
||||
|
||||
v := &graphNodeProxyProvider{
|
||||
NameValue: name,
|
||||
Path: path,
|
||||
Target: parentProvider,
|
||||
nameValue: name,
|
||||
path: path,
|
||||
target: parentProvider,
|
||||
}
|
||||
|
||||
// Add it to the graph
|
||||
g.Add(v)
|
||||
t.providers[v.NameValue] = v
|
||||
t.providers[ResolveProviderName(name, path)] = v
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -1,56 +0,0 @@
|
||||
package terraform
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/terraform/dag"
|
||||
)
|
||||
|
||||
// DisableProviderTransformer "disables" any providers that are not actually
|
||||
// used by anything, and provider proxies. This avoids the provider being
|
||||
// initialized and configured. This both saves resources but also avoids
|
||||
// errors since configuration may imply initialization which may require auth.
|
||||
type DisableProviderTransformer struct{}
|
||||
|
||||
func (t *DisableProviderTransformer) Transform(g *Graph) error {
|
||||
for _, v := range g.Vertices() {
|
||||
// We only care about providers
|
||||
pn, ok := v.(GraphNodeProvider)
|
||||
if !ok || pn.ProviderName() == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// remove the proxy nodes now that we're done with them
|
||||
if pn, ok := v.(*graphNodeProxyProvider); ok {
|
||||
g.Remove(pn)
|
||||
continue
|
||||
}
|
||||
|
||||
// If we have dependencies, then don't disable
|
||||
if g.UpEdges(v).Len() > 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// Get the path
|
||||
var path []string
|
||||
if pn, ok := v.(GraphNodeSubPath); ok {
|
||||
path = pn.Path()
|
||||
}
|
||||
|
||||
// Disable the provider by replacing it with a "disabled" provider
|
||||
disabled := &NodeDisabledProvider{
|
||||
NodeAbstractProvider: &NodeAbstractProvider{
|
||||
NameValue: pn.ProviderName(),
|
||||
PathValue: path,
|
||||
},
|
||||
}
|
||||
|
||||
if !g.Replace(v, disabled) {
|
||||
panic(fmt.Sprintf(
|
||||
"vertex disappeared from under us: %s",
|
||||
dag.VertexName(v)))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -478,6 +478,39 @@ func TestProviderConfigTransformer_parentProviders(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// the child module resource is attached to the configured grand-parent provider
|
||||
func TestProviderConfigTransformer_grandparentProviders(t *testing.T) {
|
||||
mod := testModule(t, "transform-provider-grandchild-inherit")
|
||||
concrete := func(a *NodeAbstractProvider) dag.Vertex { return a }
|
||||
|
||||
g := Graph{Path: RootModulePath}
|
||||
{
|
||||
tf := &ConfigTransformer{Module: mod}
|
||||
if err := tf.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
{
|
||||
tf := &AttachResourceConfigTransformer{Module: mod}
|
||||
if err := tf.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
tf := TransformProviders([]string{"aws"}, concrete, mod)
|
||||
if err := tf.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
actual := strings.TrimSpace(g.String())
|
||||
expected := strings.TrimSpace(testTransformModuleProviderGrandparentStr)
|
||||
if actual != expected {
|
||||
t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
const testTransformProviderBasicStr = `
|
||||
aws_instance.web
|
||||
provider.aws
|
||||
@ -514,9 +547,7 @@ module.sub.module.subsub.bar_instance.two
|
||||
module.sub.module.subsub.foo_instance.one
|
||||
module.sub.provider.foo
|
||||
module.sub.provider.foo
|
||||
provider.foo (disabled)
|
||||
provider.bar
|
||||
provider.foo (disabled)
|
||||
`
|
||||
|
||||
const testTransformMissingProviderModuleChildStr = `
|
||||
@ -584,3 +615,9 @@ module.child.aws_instance.thing
|
||||
provider.aws.foo
|
||||
provider.aws.foo
|
||||
`
|
||||
|
||||
const testTransformModuleProviderGrandparentStr = `
|
||||
module.child.module.grandchild.aws_instance.baz
|
||||
provider.aws.foo
|
||||
provider.aws.foo
|
||||
`
|
||||
|
Loading…
Reference in New Issue
Block a user