github.com/rmenn/terraform@v0.3.8-0.20150225065417-fc84b3a78802/terraform/graph_builder.go (about)

     1  package terraform
     2  
     3  import (
     4  	"log"
     5  
     6  	"github.com/hashicorp/terraform/config/module"
     7  )
     8  
     9  // GraphBuilder is an interface that can be implemented and used with
    10  // Terraform to build the graph that Terraform walks.
    11  type GraphBuilder interface {
    12  	// Build builds the graph for the given module path. It is up to
    13  	// the interface implementation whether this build should expand
    14  	// the graph or not.
    15  	Build(path []string) (*Graph, error)
    16  }
    17  
    18  // BasicGraphBuilder is a GraphBuilder that builds a graph out of a
    19  // series of transforms and validates the graph is a valid structure.
    20  type BasicGraphBuilder struct {
    21  	Steps []GraphTransformer
    22  }
    23  
    24  func (b *BasicGraphBuilder) Build(path []string) (*Graph, error) {
    25  	g := &Graph{Path: path}
    26  	for _, step := range b.Steps {
    27  		if err := step.Transform(g); err != nil {
    28  			return g, err
    29  		}
    30  
    31  		log.Printf("[TRACE] Graph after step %T:\n\n%s", step, g.String())
    32  	}
    33  
    34  	// Validate the graph structure
    35  	if err := g.Validate(); err != nil {
    36  		log.Printf("[ERROR] Graph validation failed. Graph:\n\n%s", g.String())
    37  		return nil, err
    38  	}
    39  
    40  	return g, nil
    41  }
    42  
    43  // BuiltinGraphBuilder is responsible for building the complete graph that
    44  // Terraform uses for execution. It is an opinionated builder that defines
    45  // the step order required to build a complete graph as is used and expected
    46  // by Terraform.
    47  //
    48  // If you require a custom graph, you'll have to build it up manually
    49  // on your own by building a new GraphBuilder implementation.
    50  type BuiltinGraphBuilder struct {
    51  	// Root is the root module of the graph to build.
    52  	Root *module.Tree
    53  
    54  	// Diff is the diff. The proper module diffs will be looked up.
    55  	Diff *Diff
    56  
    57  	// State is the global state. The proper module states will be looked
    58  	// up by graph path.
    59  	State *State
    60  
    61  	// Providers is the list of providers supported.
    62  	Providers []string
    63  
    64  	// Provisioners is the list of provisioners supported.
    65  	Provisioners []string
    66  }
    67  
    68  // Build builds the graph according to the steps returned by Steps.
    69  func (b *BuiltinGraphBuilder) Build(path []string) (*Graph, error) {
    70  	basic := &BasicGraphBuilder{
    71  		Steps: b.Steps(),
    72  	}
    73  
    74  	return basic.Build(path)
    75  }
    76  
    77  // Steps returns the ordered list of GraphTransformers that must be executed
    78  // to build a complete graph.
    79  func (b *BuiltinGraphBuilder) Steps() []GraphTransformer {
    80  	return []GraphTransformer{
    81  		// Create all our resources from the configuration and state
    82  		&ConfigTransformer{Module: b.Root},
    83  		&OrphanTransformer{State: b.State, Module: b.Root},
    84  
    85  		// Provider-related transformations
    86  		&MissingProviderTransformer{Providers: b.Providers},
    87  		&ProviderTransformer{},
    88  		&PruneProviderTransformer{},
    89  
    90  		// Provisioner-related transformations
    91  		&MissingProvisionerTransformer{Provisioners: b.Provisioners},
    92  		&ProvisionerTransformer{},
    93  		&PruneProvisionerTransformer{},
    94  
    95  		// Run our vertex-level transforms
    96  		&VertexTransformer{
    97  			Transforms: []GraphVertexTransformer{
    98  				// Expand any statically expanded nodes, such as module graphs
    99  				&ExpandTransform{
   100  					Builder: b,
   101  				},
   102  			},
   103  		},
   104  
   105  		// Create the destruction nodes
   106  		&DestroyTransformer{},
   107  		&CreateBeforeDestroyTransformer{},
   108  		&PruneDestroyTransformer{Diff: b.Diff, State: b.State},
   109  
   110  		// Make sure we create one root
   111  		&RootTransformer{},
   112  	}
   113  }