diff --git a/terraform/graph_builder.go b/terraform/graph_builder.go index 7963bcbf4..793dc904c 100644 --- a/terraform/graph_builder.go +++ b/terraform/graph_builder.go @@ -136,9 +136,6 @@ func (b *BuiltinGraphBuilder) Steps(path []string) []GraphTransformer { // Make sure all the connections that are proxies are connected through &ProxyTransformer{}, - - // Make sure we have a single root - &RootTransformer{}, } // If we're on the root path, then we do a bunch of other stuff. @@ -170,17 +167,15 @@ func (b *BuiltinGraphBuilder) Steps(path []string) []GraphTransformer { &CloseProviderTransformer{}, &CloseProvisionerTransformer{}, - // Make sure we have a single root after the above changes. - // This is the 2nd root transformer. In practice this shouldn't - // actually matter as the RootTransformer is idempotent. - &RootTransformer{}, - // Perform the transitive reduction to make our graph a bit // more sane if possible (it usually is possible). &TransitiveReductionTransformer{}, ) } + // Make sure we have a single root + steps = append(steps, &RootTransformer{}) + // Remove nils for i, s := range steps { if s == nil { diff --git a/terraform/transform_provisioner.go b/terraform/transform_provisioner.go index a99fe48b0..dc8513f95 100644 --- a/terraform/transform_provisioner.go +++ b/terraform/transform_provisioner.go @@ -97,15 +97,38 @@ type MissingProvisionerTransformer struct { } func (t *MissingProvisionerTransformer) Transform(g *Graph) error { + // Create a set of our supported provisioners + supported := make(map[string]struct{}, len(t.Provisioners)) + for _, v := range t.Provisioners { + supported[v] = struct{}{} + } + + // Get the map of provisioners we already have in our graph m := provisionerVertexMap(g) - for _, p := range t.Provisioners { - if _, ok := m[p]; ok { - // This provisioner already exists as a configured node + + // Go through all the provisioner consumers and make sure we add + // that provisioner if it is missing. + for _, v := range g.Vertices() { + pv, ok := v.(GraphNodeProvisionerConsumer) + if !ok { continue } - // Add our own missing provisioner node to the graph - g.Add(&graphNodeMissingProvisioner{ProvisionerNameValue: p}) + for _, p := range pv.ProvisionedBy() { + if _, ok := m[p]; ok { + // This provisioner already exists as a configure node + continue + } + + if _, ok := supported[p]; !ok { + // If we don't support the provisioner type, skip it. + // Validation later will catch this as an error. + continue + } + + // Add our own missing provisioner node to the graph + m[p] = g.Add(&graphNodeMissingProvisioner{ProvisionerNameValue: p}) + } } return nil diff --git a/terraform/transform_provisioner_test.go b/terraform/transform_provisioner_test.go index ea5faff77..823835372 100644 --- a/terraform/transform_provisioner_test.go +++ b/terraform/transform_provisioner_test.go @@ -101,7 +101,6 @@ func TestGraphNodeMissingProvisioner_ProvisionerName(t *testing.T) { const testTransformMissingProvisionerBasicStr = ` aws_instance.web -provisioner.foo provisioner.shell (close) aws_instance.web `