terraform/terraform/graph_builder.go

136 lines
3.8 KiB
Go
Raw Normal View History

2015-02-02 12:04:02 +01:00
package terraform
import (
"log"
2015-02-02 12:04:02 +01:00
"github.com/hashicorp/terraform/config/module"
)
// GraphBuilder is an interface that can be implemented and used with
// Terraform to build the graph that Terraform walks.
type GraphBuilder interface {
// Build builds the graph for the given module path. It is up to
// the interface implementation whether this build should expand
// the graph or not.
Build(path []string) (*Graph, error)
}
2015-02-08 01:19:08 +01:00
// BasicGraphBuilder is a GraphBuilder that builds a graph out of a
// series of transforms and validates the graph is a valid structure.
type BasicGraphBuilder struct {
Steps []GraphTransformer
}
func (b *BasicGraphBuilder) Build(path []string) (*Graph, error) {
g := &Graph{Path: path}
for _, step := range b.Steps {
if err := step.Transform(g); err != nil {
return g, err
}
2015-02-13 21:05:34 +01:00
log.Printf(
"[TRACE] Graph after step %T:\n\n%s",
step, g.String())
2015-02-08 01:19:08 +01:00
}
// Validate the graph structure
if err := g.Validate(); err != nil {
2015-02-13 21:05:34 +01:00
log.Printf("[ERROR] Graph validation failed. Graph:\n\n%s", g.String())
2015-02-08 01:19:08 +01:00
return nil, err
}
return g, nil
}
2015-02-02 12:04:02 +01:00
// BuiltinGraphBuilder is responsible for building the complete graph that
// Terraform uses for execution. It is an opinionated builder that defines
// the step order required to build a complete graph as is used and expected
// by Terraform.
//
// If you require a custom graph, you'll have to build it up manually
// on your own by building a new GraphBuilder implementation.
type BuiltinGraphBuilder struct {
// Root is the root module of the graph to build.
Root *module.Tree
2015-02-13 21:05:34 +01:00
// Diff is the diff. The proper module diffs will be looked up.
Diff *Diff
2015-02-02 12:04:02 +01:00
// State is the global state. The proper module states will be looked
// up by graph path.
State *State
// Providers is the list of providers supported.
Providers []string
2015-02-09 20:15:54 +01:00
// Provisioners is the list of provisioners supported.
Provisioners []string
// Targets is the user-specified list of resources to target.
Targets []string
// Destroy is set to true when we're in a `terraform destroy` or a
// `terraform plan -destroy`
Destroy bool
2015-02-02 12:04:02 +01:00
}
// Build builds the graph according to the steps returned by Steps.
func (b *BuiltinGraphBuilder) Build(path []string) (*Graph, error) {
2015-02-08 01:19:08 +01:00
basic := &BasicGraphBuilder{
Steps: b.Steps(),
2015-02-02 12:04:02 +01:00
}
2015-02-08 01:19:08 +01:00
return basic.Build(path)
2015-02-02 12:04:02 +01:00
}
// Steps returns the ordered list of GraphTransformers that must be executed
// to build a complete graph.
func (b *BuiltinGraphBuilder) Steps() []GraphTransformer {
return []GraphTransformer{
2015-02-09 19:14:09 +01:00
// Create all our resources from the configuration and state
2015-02-02 12:04:02 +01:00
&ConfigTransformer{Module: b.Root},
&OrphanTransformer{
State: b.State,
Module: b.Root,
Targeting: (len(b.Targets) > 0),
},
2015-02-09 19:14:09 +01:00
// Provider-related transformations
2015-02-02 12:04:02 +01:00
&MissingProviderTransformer{Providers: b.Providers},
&ProviderTransformer{},
&PruneProviderTransformer{},
&DisableProviderTransformer{},
2015-02-09 19:14:09 +01:00
// Provisioner-related transformations
2015-02-09 20:15:54 +01:00
&MissingProvisionerTransformer{Provisioners: b.Provisioners},
&ProvisionerTransformer{},
&PruneProvisionerTransformer{},
2015-02-09 19:14:09 +01:00
// Run our vertex-level transforms
&VertexTransformer{
Transforms: []GraphVertexTransformer{
2015-02-09 19:14:09 +01:00
// Expand any statically expanded nodes, such as module graphs
&ExpandTransform{
Builder: b,
},
},
},
2015-02-09 19:14:09 +01:00
// Optionally reduces the graph to a user-specified list of targets and
// their dependencies.
&TargetsTransformer{Targets: b.Targets, Destroy: b.Destroy},
// Create the destruction nodes
&DestroyTransformer{},
2015-02-14 00:57:37 +01:00
&CreateBeforeDestroyTransformer{},
2015-02-16 21:20:53 +01:00
&PruneDestroyTransformer{Diff: b.Diff, State: b.State},
2015-02-09 19:14:09 +01:00
// Make sure we create one root
2015-02-05 02:02:18 +01:00
&RootTransformer{},
// Perform the transitive reduction to make our graph a bit
// more sane if possible (it usually is possible).
&TransitiveReductionTransformer{},
2015-02-02 12:04:02 +01:00
}
}