terraform: ParentProviderTransform to connect parent providers

This commit is contained in:
Mitchell Hashimoto 2016-09-14 14:43:14 -07:00
parent 55ef966b88
commit 87bff933ef
No known key found for this signature in database
GPG Key ID: 744E147AA52F5B0A
6 changed files with 96 additions and 4 deletions

View File

@ -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)
}
}

View File

@ -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())
}

View File

@ -49,6 +49,7 @@ func (b *ApplyGraphBuilder) Steps() []GraphTransformer {
// Create all the providers
&MissingProviderTransformer{Providers: b.Providers},
&ProviderTransformer{},
&ParentProviderTransformer{},
// Single root
&RootTransformer{},

View File

@ -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
`

View File

@ -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

View File

@ -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 {