github.com/hashicorp/terraform-plugin-sdk@v1.17.2/terraform/graph_builder_apply.go (about)

     1  package terraform
     2  
     3  import (
     4  	"github.com/hashicorp/terraform-plugin-sdk/internal/addrs"
     5  	"github.com/hashicorp/terraform-plugin-sdk/internal/configs"
     6  	"github.com/hashicorp/terraform-plugin-sdk/internal/dag"
     7  	"github.com/hashicorp/terraform-plugin-sdk/internal/plans"
     8  	"github.com/hashicorp/terraform-plugin-sdk/internal/states"
     9  	"github.com/hashicorp/terraform-plugin-sdk/internal/tfdiags"
    10  )
    11  
    12  // ApplyGraphBuilder implements GraphBuilder and is responsible for building
    13  // a graph for applying a Terraform diff.
    14  //
    15  // Because the graph is built from the diff (vs. the config or state),
    16  // this helps ensure that the apply-time graph doesn't modify any resources
    17  // that aren't explicitly in the diff. There are other scenarios where the
    18  // diff can be deviated, so this is just one layer of protection.
    19  type ApplyGraphBuilder struct {
    20  	// Config is the configuration tree that the diff was built from.
    21  	Config *configs.Config
    22  
    23  	// Changes describes the changes that we need apply.
    24  	Changes *plans.Changes
    25  
    26  	// State is the current state
    27  	State *states.State
    28  
    29  	// Components is a factory for the plug-in components (providers and
    30  	// provisioners) available for use.
    31  	Components contextComponentFactory
    32  
    33  	// Schemas is the repository of schemas we will draw from to analyse
    34  	// the configuration.
    35  	Schemas *Schemas
    36  
    37  	// Targets are resources to target. This is only required to make sure
    38  	// unnecessary outputs aren't included in the apply graph. The plan
    39  	// builder successfully handles targeting resources. In the future,
    40  	// outputs should go into the diff so that this is unnecessary.
    41  	Targets []addrs.Targetable
    42  
    43  	// DisableReduce, if true, will not reduce the graph. Great for testing.
    44  	DisableReduce bool
    45  
    46  	// Destroy, if true, represents a pure destroy operation
    47  	Destroy bool
    48  
    49  	// Validate will do structural validation of the graph.
    50  	Validate bool
    51  }
    52  
    53  // See GraphBuilder
    54  func (b *ApplyGraphBuilder) Build(path addrs.ModuleInstance) (*Graph, tfdiags.Diagnostics) {
    55  	return (&BasicGraphBuilder{
    56  		Steps:    b.Steps(),
    57  		Validate: b.Validate,
    58  		Name:     "ApplyGraphBuilder",
    59  	}).Build(path)
    60  }
    61  
    62  // See GraphBuilder
    63  func (b *ApplyGraphBuilder) Steps() []GraphTransformer {
    64  	// Custom factory for creating providers.
    65  	concreteProvider := func(a *NodeAbstractProvider) dag.Vertex {
    66  		return &NodeApplyableProvider{
    67  			NodeAbstractProvider: a,
    68  		}
    69  	}
    70  
    71  	concreteResource := func(a *NodeAbstractResource) dag.Vertex {
    72  		return &NodeApplyableResource{
    73  			NodeAbstractResource: a,
    74  		}
    75  	}
    76  
    77  	concreteOrphanResource := func(a *NodeAbstractResource) dag.Vertex {
    78  		return &NodeDestroyResource{
    79  			NodeAbstractResource: a,
    80  		}
    81  	}
    82  
    83  	concreteResourceInstance := func(a *NodeAbstractResourceInstance) dag.Vertex {
    84  		return &NodeApplyableResourceInstance{
    85  			NodeAbstractResourceInstance: a,
    86  		}
    87  	}
    88  
    89  	steps := []GraphTransformer{
    90  		// Creates all the resources represented in the config. During apply,
    91  		// we use this just to ensure that the whole-resource metadata is
    92  		// updated to reflect things such as whether the count argument is
    93  		// set in config, or which provider configuration manages each resource.
    94  		&ConfigTransformer{
    95  			Concrete: concreteResource,
    96  			Config:   b.Config,
    97  		},
    98  
    99  		// Creates all the resource instances represented in the diff, along
   100  		// with dependency edges against the whole-resource nodes added by
   101  		// ConfigTransformer above.
   102  		&DiffTransformer{
   103  			Concrete: concreteResourceInstance,
   104  			State:    b.State,
   105  			Changes:  b.Changes,
   106  		},
   107  
   108  		// Creates extra cleanup nodes for any entire resources that are
   109  		// no longer present in config, so we can make sure we clean up the
   110  		// leftover empty resource states after the instances have been
   111  		// destroyed.
   112  		// (We don't track this particular type of change in the plan because
   113  		// it's just cleanup of our own state object, and so doesn't effect
   114  		// any real remote objects or consumable outputs.)
   115  		&OrphanResourceTransformer{
   116  			Concrete: concreteOrphanResource,
   117  			Config:   b.Config,
   118  			State:    b.State,
   119  		},
   120  
   121  		// Create orphan output nodes
   122  		&OrphanOutputTransformer{Config: b.Config, State: b.State},
   123  
   124  		// Attach the configuration to any resources
   125  		&AttachResourceConfigTransformer{Config: b.Config},
   126  
   127  		// Attach the state
   128  		&AttachStateTransformer{State: b.State},
   129  
   130  		// Provisioner-related transformations
   131  		&MissingProvisionerTransformer{Provisioners: b.Components.ResourceProvisioners()},
   132  		&ProvisionerTransformer{},
   133  
   134  		// Add root variables
   135  		&RootVariableTransformer{Config: b.Config},
   136  
   137  		// Add the local values
   138  		&LocalTransformer{Config: b.Config},
   139  
   140  		// Add the outputs
   141  		&OutputTransformer{Config: b.Config},
   142  
   143  		// Add module variables
   144  		&ModuleVariableTransformer{Config: b.Config},
   145  
   146  		// add providers
   147  		TransformProviders(b.Components.ResourceProviders(), concreteProvider, b.Config),
   148  
   149  		// Remove modules no longer present in the config
   150  		&RemovedModuleTransformer{Config: b.Config, State: b.State},
   151  
   152  		// Must attach schemas before ReferenceTransformer so that we can
   153  		// analyze the configuration to find references.
   154  		&AttachSchemaTransformer{Schemas: b.Schemas},
   155  
   156  		// Connect references so ordering is correct
   157  		&ReferenceTransformer{},
   158  
   159  		// Destruction ordering
   160  		&DestroyEdgeTransformer{
   161  			Config:  b.Config,
   162  			State:   b.State,
   163  			Schemas: b.Schemas,
   164  		},
   165  
   166  		&CBDEdgeTransformer{
   167  			Config:  b.Config,
   168  			State:   b.State,
   169  			Schemas: b.Schemas,
   170  			Destroy: b.Destroy,
   171  		},
   172  
   173  		// Handle destroy time transformations for output and local values.
   174  		// Reverse the edges from outputs and locals, so that
   175  		// interpolations don't fail during destroy.
   176  		// Create a destroy node for outputs to remove them from the state.
   177  		// Prune unreferenced values, which may have interpolations that can't
   178  		// be resolved.
   179  		GraphTransformIf(
   180  			func() bool { return b.Destroy },
   181  			GraphTransformMulti(
   182  				&DestroyValueReferenceTransformer{},
   183  				&DestroyOutputTransformer{},
   184  				&PruneUnusedValuesTransformer{},
   185  			),
   186  		),
   187  
   188  		// Add the node to fix the state count boundaries
   189  		&CountBoundaryTransformer{
   190  			Config: b.Config,
   191  		},
   192  
   193  		// Target
   194  		&TargetsTransformer{Targets: b.Targets},
   195  
   196  		// Close opened plugin connections
   197  		&CloseProviderTransformer{},
   198  		&CloseProvisionerTransformer{},
   199  
   200  		// Single root
   201  		&RootTransformer{},
   202  	}
   203  
   204  	if !b.DisableReduce {
   205  		// Perform the transitive reduction to make our graph a bit
   206  		// more sane if possible (it usually is possible).
   207  		steps = append(steps, &TransitiveReductionTransformer{})
   208  	}
   209  
   210  	return steps
   211  }