github.com/hs0210/hashicorp-terraform@v0.11.12-beta1/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  		// add providers
    91  		TransformProviders(b.Providers, concreteProvider, b.Module),
    92  
    93  		// Destruction ordering
    94  		&DestroyEdgeTransformer{Module: b.Module, State: b.State},
    95  		GraphTransformIf(
    96  			func() bool { return !b.Destroy },
    97  			&CBDEdgeTransformer{Module: b.Module, State: b.State},
    98  		),
    99  
   100  		// Provisioner-related transformations
   101  		&MissingProvisionerTransformer{Provisioners: b.Provisioners},
   102  		&ProvisionerTransformer{},
   103  
   104  		// Add root variables
   105  		&RootVariableTransformer{Module: b.Module},
   106  
   107  		// Add the local values
   108  		&LocalTransformer{Module: b.Module},
   109  
   110  		// Add the outputs
   111  		&OutputTransformer{Module: b.Module},
   112  
   113  		// Add module variables
   114  		&ModuleVariableTransformer{Module: b.Module},
   115  
   116  		// Remove modules no longer present in the config
   117  		&RemovedModuleTransformer{Module: b.Module, State: b.State},
   118  
   119  		// Connect references so ordering is correct
   120  		&ReferenceTransformer{},
   121  
   122  		// Handle destroy time transformations for output and local values.
   123  		// Reverse the edges from outputs and locals, so that
   124  		// interpolations don't fail during destroy.
   125  		// Create a destroy node for outputs to remove them from the state.
   126  		// Prune unreferenced values, which may have interpolations that can't
   127  		// be resolved.
   128  		GraphTransformIf(
   129  			func() bool { return b.Destroy },
   130  			GraphTransformMulti(
   131  				&DestroyValueReferenceTransformer{},
   132  				&DestroyOutputTransformer{},
   133  				&PruneUnusedValuesTransformer{},
   134  			),
   135  		),
   136  
   137  		// Add the node to fix the state count boundaries
   138  		&CountBoundaryTransformer{},
   139  
   140  		// Target
   141  		&TargetsTransformer{Targets: b.Targets},
   142  
   143  		// Close opened plugin connections
   144  		&CloseProviderTransformer{},
   145  		&CloseProvisionerTransformer{},
   146  
   147  		// Single root
   148  		&RootTransformer{},
   149  	}
   150  
   151  	if !b.DisableReduce {
   152  		// Perform the transitive reduction to make our graph a bit
   153  		// more sane if possible (it usually is possible).
   154  		steps = append(steps, &TransitiveReductionTransformer{})
   155  	}
   156  
   157  	return steps
   158  }