mirror of
https://github.com/opentofu/opentofu.git
synced 2025-01-13 09:32:24 -06:00
terraform: ParentProviderTransform to connect parent providers
This commit is contained in:
parent
55ef966b88
commit
87bff933ef
@ -1232,7 +1232,7 @@ aws_instance.foo:
|
||||
}
|
||||
}
|
||||
|
||||
func TestContext2Apply_module(t *testing.T) {
|
||||
func TestContext2Apply_moduleBasic(t *testing.T) {
|
||||
m := testModule(t, "apply-module")
|
||||
p := testProvider("aws")
|
||||
p.ApplyFn = testApplyFn
|
||||
@ -1256,7 +1256,7 @@ func TestContext2Apply_module(t *testing.T) {
|
||||
actual := strings.TrimSpace(state.String())
|
||||
expected := strings.TrimSpace(testTerraformApplyModuleStr)
|
||||
if actual != expected {
|
||||
t.Fatalf("bad: \n%s", actual)
|
||||
t.Fatalf("bad, expected:\n%s\n\nactual:\n%s", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,7 +230,7 @@ func (g *Graph) walk(walker GraphWalker) error {
|
||||
// with a GraphNodeSubPath impl.
|
||||
vertexCtx := ctx
|
||||
if pn, ok := v.(GraphNodeSubPath); ok && len(pn.Path()) > 0 {
|
||||
vertexCtx = walker.EnterPath(pn.Path())
|
||||
vertexCtx = walker.EnterPath(normalizeModulePath(pn.Path()))
|
||||
defer walker.ExitPath(pn.Path())
|
||||
}
|
||||
|
||||
|
@ -49,6 +49,7 @@ func (b *ApplyGraphBuilder) Steps() []GraphTransformer {
|
||||
// Create all the providers
|
||||
&MissingProviderTransformer{Providers: b.Providers},
|
||||
&ProviderTransformer{},
|
||||
&ParentProviderTransformer{},
|
||||
|
||||
// Single root
|
||||
&RootTransformer{},
|
||||
|
@ -29,6 +29,20 @@ func TestApplyGraphBuilder(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
&ModuleDiff{
|
||||
Path: []string{"root", "child"},
|
||||
Resources: map[string]*InstanceDiff{
|
||||
"aws_instance.create": &InstanceDiff{
|
||||
Attributes: map[string]*ResourceAttrDiff{
|
||||
"name": &ResourceAttrDiff{
|
||||
Old: "",
|
||||
New: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -56,5 +70,12 @@ func TestApplyGraphBuilder(t *testing.T) {
|
||||
const testApplyGraphBuilderStr = `
|
||||
aws_instance.create
|
||||
provider.aws
|
||||
module.child.aws_instance.create
|
||||
module.child.provider.aws
|
||||
module.child.provider.aws
|
||||
provider.aws
|
||||
provider.aws
|
||||
root
|
||||
aws_instance.create
|
||||
module.child.aws_instance.create
|
||||
`
|
||||
|
@ -18,6 +18,11 @@ func (n *NodeApplyableResource) Name() string {
|
||||
return n.Addr.String()
|
||||
}
|
||||
|
||||
// GraphNodeSubPath
|
||||
func (n *NodeApplyableResource) Path() []string {
|
||||
return n.Addr.Path
|
||||
}
|
||||
|
||||
// GraphNodeProviderConsumer
|
||||
func (n *NodeApplyableResource) ProvidedBy() []string {
|
||||
// If we have a config we prefer that above all else
|
||||
|
@ -217,7 +217,11 @@ func (t *MissingProviderTransformer) Transform(g *Graph) error {
|
||||
}
|
||||
|
||||
// Add the missing provider node to the graph
|
||||
raw := &graphNodeProvider{ProviderNameValue: p}
|
||||
raw := &graphNodeProvider{
|
||||
ProviderNameValue: p,
|
||||
PathValue: path,
|
||||
}
|
||||
|
||||
var v dag.Vertex = raw
|
||||
if len(path) > 0 {
|
||||
var err error
|
||||
@ -242,6 +246,66 @@ func (t *MissingProviderTransformer) Transform(g *Graph) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParentProviderTransformer connects provider nodes to their parents.
|
||||
//
|
||||
// This works by finding nodes that are both GraphNodeProviders and
|
||||
// GraphNodeSubPath. It then connects the providers to their parent
|
||||
// path.
|
||||
type ParentProviderTransformer struct{}
|
||||
|
||||
func (t *ParentProviderTransformer) Transform(g *Graph) error {
|
||||
// Make a mapping of path to dag.Vertex, where path is: "path.name"
|
||||
m := make(map[string]dag.Vertex)
|
||||
|
||||
// Also create a map that maps a provider to its parent
|
||||
parentMap := make(map[dag.Vertex]string)
|
||||
for _, raw := range g.Vertices() {
|
||||
// If it is the flat version, then make it the non-flat version.
|
||||
// We eventually want to get rid of the flat version entirely so
|
||||
// this is a stop-gap while it still exists.
|
||||
var v dag.Vertex = raw
|
||||
if f, ok := v.(*graphNodeProviderFlat); ok {
|
||||
v = f.graphNodeProvider
|
||||
}
|
||||
|
||||
// Only care about providers
|
||||
pn, ok := v.(GraphNodeProvider)
|
||||
if !ok || pn.ProviderName() == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Also require a subpath, if there is no subpath then we
|
||||
// just totally ignore it. The expectation of this transform is
|
||||
// that it is used with a graph builder that is already flattened.
|
||||
var path []string
|
||||
if pn, ok := raw.(GraphNodeSubPath); ok {
|
||||
path = pn.Path()
|
||||
}
|
||||
path = normalizeModulePath(path)
|
||||
|
||||
// Build the key with path.name i.e. "child.subchild.aws"
|
||||
key := fmt.Sprintf("%s.%s", strings.Join(path, "."), pn.ProviderName())
|
||||
m[key] = v
|
||||
|
||||
// Determine the parent if we're non-root. This is length 1 since
|
||||
// the 0 index should be "root" since we normalize above.
|
||||
if len(path) > 1 {
|
||||
path = path[:len(path)-1]
|
||||
key := fmt.Sprintf("%s.%s", strings.Join(path, "."), pn.ProviderName())
|
||||
parentMap[raw] = key
|
||||
}
|
||||
}
|
||||
|
||||
// Connect!
|
||||
for v, key := range parentMap {
|
||||
if parent, ok := m[key]; ok {
|
||||
g.Connect(dag.BasicEdge(v, parent))
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
@ -448,6 +512,7 @@ func (n *graphNodeCloseProvider) DotNode(name string, opts *GraphDotOpts) *dot.N
|
||||
|
||||
type graphNodeProvider struct {
|
||||
ProviderNameValue string
|
||||
PathValue []string
|
||||
}
|
||||
|
||||
func (n *graphNodeProvider) Name() string {
|
||||
|
Loading…
Reference in New Issue
Block a user