github.com/muratcelep/terraform@v1.1.0-beta2-not-internal-4/not-internal/terraform/graph_builder_plan.go (about)

     1  package terraform
     2  
     3  import (
     4  	"sync"
     5  
     6  	"github.com/muratcelep/terraform/not-internal/addrs"
     7  	"github.com/muratcelep/terraform/not-internal/configs"
     8  	"github.com/muratcelep/terraform/not-internal/dag"
     9  	"github.com/muratcelep/terraform/not-internal/states"
    10  	"github.com/muratcelep/terraform/not-internal/tfdiags"
    11  )
    12  
    13  // PlanGraphBuilder implements GraphBuilder and is responsible for building
    14  // a graph for planning (creating a Terraform Diff).
    15  //
    16  // The primary difference between this graph and others:
    17  //
    18  //   * Based on the config since it represents the target state
    19  //
    20  //   * Ignores lifecycle options since no lifecycle events occur here. This
    21  //     simplifies the graph significantly since complex transforms such as
    22  //     create-before-destroy can be completely ignored.
    23  //
    24  type PlanGraphBuilder struct {
    25  	// Config is the configuration tree to build a plan from.
    26  	Config *configs.Config
    27  
    28  	// State is the current state
    29  	State *states.State
    30  
    31  	// Plugins is a library of plug-in components (providers and
    32  	// provisioners) available for use.
    33  	Plugins *contextPlugins
    34  
    35  	// Targets are resources to target
    36  	Targets []addrs.Targetable
    37  
    38  	// ForceReplace are resource instances where if we would normally have
    39  	// generated a NoOp or Update action then we'll force generating a replace
    40  	// action instead. Create and Delete actions are not affected.
    41  	ForceReplace []addrs.AbsResourceInstance
    42  
    43  	// Validate will do structural validation of the graph.
    44  	Validate bool
    45  
    46  	// skipRefresh indicates that we should skip refreshing managed resources
    47  	skipRefresh bool
    48  
    49  	// skipPlanChanges indicates that we should skip the step of comparing
    50  	// prior state with configuration and generating planned changes to
    51  	// resource instances. (This is for the "refresh only" planning mode,
    52  	// where we _only_ do the refresh step.)
    53  	skipPlanChanges bool
    54  
    55  	// CustomConcrete can be set to customize the node types created
    56  	// for various parts of the plan. This is useful in order to customize
    57  	// the plan behavior.
    58  	CustomConcrete         bool
    59  	ConcreteProvider       ConcreteProviderNodeFunc
    60  	ConcreteResource       ConcreteResourceNodeFunc
    61  	ConcreteResourceOrphan ConcreteResourceInstanceNodeFunc
    62  	ConcreteModule         ConcreteModuleNodeFunc
    63  
    64  	once sync.Once
    65  }
    66  
    67  // See GraphBuilder
    68  func (b *PlanGraphBuilder) Build(path addrs.ModuleInstance) (*Graph, tfdiags.Diagnostics) {
    69  	return (&BasicGraphBuilder{
    70  		Steps:    b.Steps(),
    71  		Validate: b.Validate,
    72  		Name:     "PlanGraphBuilder",
    73  	}).Build(path)
    74  }
    75  
    76  // See GraphBuilder
    77  func (b *PlanGraphBuilder) Steps() []GraphTransformer {
    78  	b.once.Do(b.init)
    79  
    80  	concreteResourceInstanceDeposed := func(a *NodeAbstractResourceInstance, key states.DeposedKey) dag.Vertex {
    81  		return &NodePlanDeposedResourceInstanceObject{
    82  			NodeAbstractResourceInstance: a,
    83  			DeposedKey:                   key,
    84  
    85  			skipRefresh:     b.skipRefresh,
    86  			skipPlanChanges: b.skipPlanChanges,
    87  		}
    88  	}
    89  
    90  	steps := []GraphTransformer{
    91  		// Creates all the resources represented in the config
    92  		&ConfigTransformer{
    93  			Concrete: b.ConcreteResource,
    94  			Config:   b.Config,
    95  		},
    96  
    97  		// Add dynamic values
    98  		&RootVariableTransformer{Config: b.Config},
    99  		&ModuleVariableTransformer{Config: b.Config},
   100  		&LocalTransformer{Config: b.Config},
   101  		&OutputTransformer{Config: b.Config},
   102  
   103  		// Add orphan resources
   104  		&OrphanResourceInstanceTransformer{
   105  			Concrete: b.ConcreteResourceOrphan,
   106  			State:    b.State,
   107  			Config:   b.Config,
   108  		},
   109  
   110  		// We also need nodes for any deposed instance objects present in the
   111  		// state, so we can plan to destroy them. (This intentionally
   112  		// skips creating nodes for _current_ objects, since ConfigTransformer
   113  		// created nodes that will do that during DynamicExpand.)
   114  		&StateTransformer{
   115  			ConcreteDeposed: concreteResourceInstanceDeposed,
   116  			State:           b.State,
   117  		},
   118  
   119  		// Attach the state
   120  		&AttachStateTransformer{State: b.State},
   121  
   122  		// Create orphan output nodes
   123  		&OrphanOutputTransformer{Config: b.Config, State: b.State},
   124  
   125  		// Attach the configuration to any resources
   126  		&AttachResourceConfigTransformer{Config: b.Config},
   127  
   128  		// add providers
   129  		transformProviders(b.ConcreteProvider, b.Config),
   130  
   131  		// Remove modules no longer present in the config
   132  		&RemovedModuleTransformer{Config: b.Config, State: b.State},
   133  
   134  		// Must attach schemas before ReferenceTransformer so that we can
   135  		// analyze the configuration to find references.
   136  		&AttachSchemaTransformer{Plugins: b.Plugins, Config: b.Config},
   137  
   138  		// Create expansion nodes for all of the module calls. This must
   139  		// come after all other transformers that create nodes representing
   140  		// objects that can belong to modules.
   141  		&ModuleExpansionTransformer{Concrete: b.ConcreteModule, Config: b.Config},
   142  
   143  		// Connect so that the references are ready for targeting. We'll
   144  		// have to connect again later for providers and so on.
   145  		&ReferenceTransformer{},
   146  		&AttachDependenciesTransformer{},
   147  
   148  		// Make sure data sources are aware of any depends_on from the
   149  		// configuration
   150  		&attachDataResourceDependsOnTransformer{},
   151  
   152  		// Target
   153  		&TargetsTransformer{Targets: b.Targets},
   154  
   155  		// Detect when create_before_destroy must be forced on for a particular
   156  		// node due to dependency edges, to avoid graph cycles during apply.
   157  		&ForcedCBDTransformer{},
   158  
   159  		// Close opened plugin connections
   160  		&CloseProviderTransformer{},
   161  
   162  		// Close the root module
   163  		&CloseRootModuleTransformer{},
   164  
   165  		// Perform the transitive reduction to make our graph a bit
   166  		// more understandable if possible (it usually is possible).
   167  		&TransitiveReductionTransformer{},
   168  	}
   169  
   170  	return steps
   171  }
   172  
   173  func (b *PlanGraphBuilder) init() {
   174  	// Do nothing if the user requests customizing the fields
   175  	if b.CustomConcrete {
   176  		return
   177  	}
   178  
   179  	b.ConcreteProvider = func(a *NodeAbstractProvider) dag.Vertex {
   180  		return &NodeApplyableProvider{
   181  			NodeAbstractProvider: a,
   182  		}
   183  	}
   184  
   185  	b.ConcreteResource = func(a *NodeAbstractResource) dag.Vertex {
   186  		return &nodeExpandPlannableResource{
   187  			NodeAbstractResource: a,
   188  			skipRefresh:          b.skipRefresh,
   189  			skipPlanChanges:      b.skipPlanChanges,
   190  			forceReplace:         b.ForceReplace,
   191  		}
   192  	}
   193  
   194  	b.ConcreteResourceOrphan = func(a *NodeAbstractResourceInstance) dag.Vertex {
   195  		return &NodePlannableResourceInstanceOrphan{
   196  			NodeAbstractResourceInstance: a,
   197  			skipRefresh:                  b.skipRefresh,
   198  			skipPlanChanges:              b.skipPlanChanges,
   199  		}
   200  	}
   201  }