github.com/paybyphone/terraform@v0.9.5-0.20170613192930-9706042ddd51/terraform/graph_builder_plan.go (about)

     1  package terraform
     2  
     3  import (
     4  	"sync"
     5  
     6  	"github.com/hashicorp/terraform/config/module"
     7  	"github.com/hashicorp/terraform/dag"
     8  )
     9  
    10  // PlanGraphBuilder implements GraphBuilder and is responsible for building
    11  // a graph for planning (creating a Terraform Diff).
    12  //
    13  // The primary difference between this graph and others:
    14  //
    15  //   * Based on the config since it represents the target state
    16  //
    17  //   * Ignores lifecycle options since no lifecycle events occur here. This
    18  //     simplifies the graph significantly since complex transforms such as
    19  //     create-before-destroy can be completely ignored.
    20  //
    21  type PlanGraphBuilder struct {
    22  	// Module is the root module for the graph to build.
    23  	Module *module.Tree
    24  
    25  	// State is the current state
    26  	State *State
    27  
    28  	// Providers is the list of providers supported.
    29  	Providers []string
    30  
    31  	// Provisioners is the list of provisioners supported.
    32  	Provisioners []string
    33  
    34  	// Targets are resources to target
    35  	Targets []string
    36  
    37  	// DisableReduce, if true, will not reduce the graph. Great for testing.
    38  	DisableReduce bool
    39  
    40  	// Validate will do structural validation of the graph.
    41  	Validate bool
    42  
    43  	// CustomConcrete can be set to customize the node types created
    44  	// for various parts of the plan. This is useful in order to customize
    45  	// the plan behavior.
    46  	CustomConcrete         bool
    47  	ConcreteProvider       ConcreteProviderNodeFunc
    48  	ConcreteResource       ConcreteResourceNodeFunc
    49  	ConcreteResourceOrphan ConcreteResourceNodeFunc
    50  
    51  	once sync.Once
    52  }
    53  
    54  // See GraphBuilder
    55  func (b *PlanGraphBuilder) Build(path []string) (*Graph, error) {
    56  	return (&BasicGraphBuilder{
    57  		Steps:    b.Steps(),
    58  		Validate: b.Validate,
    59  		Name:     "PlanGraphBuilder",
    60  	}).Build(path)
    61  }
    62  
    63  // See GraphBuilder
    64  func (b *PlanGraphBuilder) Steps() []GraphTransformer {
    65  	b.once.Do(b.init)
    66  
    67  	steps := []GraphTransformer{
    68  		// Creates all the resources represented in the config
    69  		&ConfigTransformer{
    70  			Concrete: b.ConcreteResource,
    71  			Module:   b.Module,
    72  		},
    73  
    74  		// Add the outputs
    75  		&OutputTransformer{Module: b.Module},
    76  
    77  		// Add orphan resources
    78  		&OrphanResourceTransformer{
    79  			Concrete: b.ConcreteResourceOrphan,
    80  			State:    b.State,
    81  			Module:   b.Module,
    82  		},
    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 root variables
    91  		&RootVariableTransformer{Module: b.Module},
    92  
    93  		// Create all the providers
    94  		&MissingProviderTransformer{Providers: b.Providers, Concrete: b.ConcreteProvider},
    95  		&ProviderTransformer{},
    96  		&DisableProviderTransformer{},
    97  		&ParentProviderTransformer{},
    98  		&AttachProviderConfigTransformer{Module: b.Module},
    99  
   100  		// Provisioner-related transformations. Only add these if requested.
   101  		GraphTransformIf(
   102  			func() bool { return b.Provisioners != nil },
   103  			GraphTransformMulti(
   104  				&MissingProvisionerTransformer{Provisioners: b.Provisioners},
   105  				&ProvisionerTransformer{},
   106  			),
   107  		),
   108  
   109  		// Add module variables
   110  		&ModuleVariableTransformer{Module: b.Module},
   111  
   112  		// Connect so that the references are ready for targeting. We'll
   113  		// have to connect again later for providers and so on.
   114  		&ReferenceTransformer{},
   115  
   116  		// Add the node to fix the state count boundaries
   117  		&CountBoundaryTransformer{},
   118  
   119  		// Target
   120  		&TargetsTransformer{Targets: b.Targets},
   121  
   122  		// Close opened plugin connections
   123  		&CloseProviderTransformer{},
   124  		&CloseProvisionerTransformer{},
   125  
   126  		// Single root
   127  		&RootTransformer{},
   128  	}
   129  
   130  	if !b.DisableReduce {
   131  		// Perform the transitive reduction to make our graph a bit
   132  		// more sane if possible (it usually is possible).
   133  		steps = append(steps, &TransitiveReductionTransformer{})
   134  	}
   135  
   136  	return steps
   137  }
   138  
   139  func (b *PlanGraphBuilder) init() {
   140  	// Do nothing if the user requests customizing the fields
   141  	if b.CustomConcrete {
   142  		return
   143  	}
   144  
   145  	b.ConcreteProvider = func(a *NodeAbstractProvider) dag.Vertex {
   146  		return &NodeApplyableProvider{
   147  			NodeAbstractProvider: a,
   148  		}
   149  	}
   150  
   151  	b.ConcreteResource = func(a *NodeAbstractResource) dag.Vertex {
   152  		return &NodePlannableResource{
   153  			NodeAbstractCountResource: &NodeAbstractCountResource{
   154  				NodeAbstractResource: a,
   155  			},
   156  		}
   157  	}
   158  
   159  	b.ConcreteResourceOrphan = func(a *NodeAbstractResource) dag.Vertex {
   160  		return &NodePlannableResourceOrphan{
   161  			NodeAbstractResource: a,
   162  		}
   163  	}
   164  }