github.com/ns1/terraform@v0.7.10-0.20161109153551-8949419bef40/terraform/graph_builder_apply.go (about)

     1  package terraform
     2  
     3  import (
     4  	"github.com/hashicorp/terraform/config/module"
     5  	"github.com/hashicorp/terraform/dag"
     6  )
     7  
     8  // ApplyGraphBuilder implements GraphBuilder and is responsible for building
     9  // a graph for applying a Terraform diff.
    10  //
    11  // Because the graph is built from the diff (vs. the config or state),
    12  // this helps ensure that the apply-time graph doesn't modify any resources
    13  // that aren't explicitly in the diff. There are other scenarios where the
    14  // diff can be deviated, so this is just one layer of protection.
    15  type ApplyGraphBuilder struct {
    16  	// Module is the root module for the graph to build.
    17  	Module *module.Tree
    18  
    19  	// Diff is the diff to apply.
    20  	Diff *Diff
    21  
    22  	// State is the current state
    23  	State *State
    24  
    25  	// Providers is the list of providers supported.
    26  	Providers []string
    27  
    28  	// Provisioners is the list of provisioners supported.
    29  	Provisioners []string
    30  
    31  	// DisableReduce, if true, will not reduce the graph. Great for testing.
    32  	DisableReduce bool
    33  
    34  	// Destroy, if true, represents a pure destroy operation
    35  	Destroy bool
    36  }
    37  
    38  // See GraphBuilder
    39  func (b *ApplyGraphBuilder) Build(path []string) (*Graph, error) {
    40  	return (&BasicGraphBuilder{
    41  		Steps:    b.Steps(),
    42  		Validate: true,
    43  		Name:     "apply",
    44  	}).Build(path)
    45  }
    46  
    47  // See GraphBuilder
    48  func (b *ApplyGraphBuilder) Steps() []GraphTransformer {
    49  	// Custom factory for creating providers.
    50  	providerFactory := func(name string, path []string) GraphNodeProvider {
    51  		return &NodeApplyableProvider{
    52  			NameValue: name,
    53  			PathValue: path,
    54  		}
    55  	}
    56  
    57  	concreteResource := func(a *NodeAbstractResource) dag.Vertex {
    58  		return &NodeApplyableResource{
    59  			NodeAbstractResource: a,
    60  		}
    61  	}
    62  
    63  	steps := []GraphTransformer{
    64  		// Creates all the nodes represented in the diff.
    65  		&DiffTransformer{
    66  			Concrete: concreteResource,
    67  
    68  			Diff:   b.Diff,
    69  			Module: b.Module,
    70  			State:  b.State,
    71  		},
    72  
    73  		// Create orphan output nodes
    74  		&OrphanOutputTransformer{Module: b.Module, State: b.State},
    75  
    76  		// Attach the configuration to any resources
    77  		&AttachResourceConfigTransformer{Module: b.Module},
    78  
    79  		// Attach the state
    80  		&AttachStateTransformer{State: b.State},
    81  
    82  		// Destruction ordering
    83  		&DestroyEdgeTransformer{Module: b.Module, State: b.State},
    84  		GraphTransformIf(
    85  			func() bool { return !b.Destroy },
    86  			&CBDEdgeTransformer{Module: b.Module, State: b.State},
    87  		),
    88  
    89  		// Create all the providers
    90  		&MissingProviderTransformer{Providers: b.Providers, Factory: providerFactory},
    91  		&ProviderTransformer{},
    92  		&DisableProviderTransformer{},
    93  		&ParentProviderTransformer{},
    94  		&AttachProviderConfigTransformer{Module: b.Module},
    95  
    96  		// Provisioner-related transformations
    97  		GraphTransformIf(
    98  			func() bool { return !b.Destroy },
    99  			GraphTransformMulti(
   100  				&MissingProvisionerTransformer{Provisioners: b.Provisioners},
   101  				&ProvisionerTransformer{},
   102  			),
   103  		),
   104  
   105  		// Add root variables
   106  		&RootVariableTransformer{Module: b.Module},
   107  
   108  		// Add the outputs
   109  		&OutputTransformer{Module: b.Module},
   110  
   111  		// Add module variables
   112  		&ModuleVariableTransformer{Module: b.Module},
   113  
   114  		// Connect references so ordering is correct
   115  		&ReferenceTransformer{},
   116  
   117  		// Add the node to fix the state count boundaries
   118  		&CountBoundaryTransformer{},
   119  
   120  		// Single root
   121  		&RootTransformer{},
   122  	}
   123  
   124  	if !b.DisableReduce {
   125  		// Perform the transitive reduction to make our graph a bit
   126  		// more sane if possible (it usually is possible).
   127  		steps = append(steps, &TransitiveReductionTransformer{})
   128  	}
   129  
   130  	return steps
   131  }