github.com/ibm-cloud/terraform@v0.6.4-0.20170726051544-8872b87621df/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  	// Targets are resources to target. This is only required to make sure
    32  	// unnecessary outputs aren't included in the apply graph. The plan
    33  	// builder successfully handles targeting resources. In the future,
    34  	// outputs should go into the diff so that this is unnecessary.
    35  	Targets []string
    36  
    37  	// DisableReduce, if true, will not reduce the graph. Great for testing.
    38  	DisableReduce bool
    39  
    40  	// Destroy, if true, represents a pure destroy operation
    41  	Destroy bool
    42  
    43  	// Validate will do structural validation of the graph.
    44  	Validate bool
    45  }
    46  
    47  // See GraphBuilder
    48  func (b *ApplyGraphBuilder) Build(path []string) (*Graph, error) {
    49  	return (&BasicGraphBuilder{
    50  		Steps:    b.Steps(),
    51  		Validate: b.Validate,
    52  		Name:     "ApplyGraphBuilder",
    53  	}).Build(path)
    54  }
    55  
    56  // See GraphBuilder
    57  func (b *ApplyGraphBuilder) Steps() []GraphTransformer {
    58  	// Custom factory for creating providers.
    59  	concreteProvider := func(a *NodeAbstractProvider) dag.Vertex {
    60  		return &NodeApplyableProvider{
    61  			NodeAbstractProvider: a,
    62  		}
    63  	}
    64  
    65  	concreteResource := func(a *NodeAbstractResource) dag.Vertex {
    66  		return &NodeApplyableResource{
    67  			NodeAbstractResource: a,
    68  		}
    69  	}
    70  
    71  	steps := []GraphTransformer{
    72  		// Creates all the nodes represented in the diff.
    73  		&DiffTransformer{
    74  			Concrete: concreteResource,
    75  
    76  			Diff:   b.Diff,
    77  			Module: b.Module,
    78  			State:  b.State,
    79  		},
    80  
    81  		// Create orphan output nodes
    82  		&OrphanOutputTransformer{Module: b.Module, State: b.State},
    83  
    84  		// Attach the configuration to any resources
    85  		&AttachResourceConfigTransformer{Module: b.Module},
    86  
    87  		// Attach the state
    88  		&AttachStateTransformer{State: b.State},
    89  
    90  		// Create all the providers
    91  		&MissingProviderTransformer{Providers: b.Providers, Concrete: concreteProvider},
    92  		&ProviderTransformer{},
    93  		&DisableProviderTransformer{},
    94  		&ParentProviderTransformer{},
    95  		&AttachProviderConfigTransformer{Module: b.Module},
    96  
    97  		// Destruction ordering
    98  		&DestroyEdgeTransformer{Module: b.Module, State: b.State},
    99  		GraphTransformIf(
   100  			func() bool { return !b.Destroy },
   101  			&CBDEdgeTransformer{Module: b.Module, State: b.State},
   102  		),
   103  
   104  		// Provisioner-related transformations
   105  		&MissingProvisionerTransformer{Provisioners: b.Provisioners},
   106  		&ProvisionerTransformer{},
   107  
   108  		// Add root variables
   109  		&RootVariableTransformer{Module: b.Module},
   110  
   111  		// Add the outputs
   112  		&OutputTransformer{Module: b.Module},
   113  
   114  		// Add module variables
   115  		&ModuleVariableTransformer{Module: b.Module},
   116  
   117  		// Connect references so ordering is correct
   118  		&ReferenceTransformer{},
   119  
   120  		// Add the node to fix the state count boundaries
   121  		&CountBoundaryTransformer{},
   122  
   123  		// Target
   124  		&TargetsTransformer{Targets: b.Targets},
   125  
   126  		// Close opened plugin connections
   127  		&CloseProviderTransformer{},
   128  		&CloseProvisionerTransformer{},
   129  
   130  		// Single root
   131  		&RootTransformer{},
   132  	}
   133  
   134  	if !b.DisableReduce {
   135  		// Perform the transitive reduction to make our graph a bit
   136  		// more sane if possible (it usually is possible).
   137  		steps = append(steps, &TransitiveReductionTransformer{})
   138  	}
   139  
   140  	return steps
   141  }