kubeform.dev/terraform-backend-sdk@v0.0.0-20220310143633-45f07fe731c5/terraform/graph_builder_apply.go (about)

     1  package terraform
     2  
     3  import (
     4  	"kubeform.dev/terraform-backend-sdk/addrs"
     5  	"kubeform.dev/terraform-backend-sdk/configs"
     6  	"kubeform.dev/terraform-backend-sdk/dag"
     7  	"kubeform.dev/terraform-backend-sdk/plans"
     8  	"kubeform.dev/terraform-backend-sdk/states"
     9  	"kubeform.dev/terraform-backend-sdk/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  	// Plugins is a library of the plug-in components (providers and
    30  	// provisioners) available for use.
    31  	Plugins *contextPlugins
    32  
    33  	// Targets are resources to target. This is only required to make sure
    34  	// unnecessary outputs aren't included in the apply graph. The plan
    35  	// builder successfully handles targeting resources. In the future,
    36  	// outputs should go into the diff so that this is unnecessary.
    37  	Targets []addrs.Targetable
    38  
    39  	// ForceReplace are the resource instance addresses that the user
    40  	// requested to force replacement for when creating the plan, if any.
    41  	// The apply step refers to these as part of verifying that the planned
    42  	// actions remain consistent between plan and apply.
    43  	ForceReplace []addrs.AbsResourceInstance
    44  
    45  	// Validate will do structural validation of the graph.
    46  	Validate bool
    47  }
    48  
    49  // See GraphBuilder
    50  func (b *ApplyGraphBuilder) Build(path addrs.ModuleInstance) (*Graph, tfdiags.Diagnostics) {
    51  	return (&BasicGraphBuilder{
    52  		Steps:    b.Steps(),
    53  		Validate: b.Validate,
    54  		Name:     "ApplyGraphBuilder",
    55  	}).Build(path)
    56  }
    57  
    58  // See GraphBuilder
    59  func (b *ApplyGraphBuilder) Steps() []GraphTransformer {
    60  	// Custom factory for creating providers.
    61  	concreteProvider := func(a *NodeAbstractProvider) dag.Vertex {
    62  		return &NodeApplyableProvider{
    63  			NodeAbstractProvider: a,
    64  		}
    65  	}
    66  
    67  	concreteResource := func(a *NodeAbstractResource) dag.Vertex {
    68  		return &nodeExpandApplyableResource{
    69  			NodeAbstractResource: a,
    70  		}
    71  	}
    72  
    73  	concreteResourceInstance := func(a *NodeAbstractResourceInstance) dag.Vertex {
    74  		return &NodeApplyableResourceInstance{
    75  			NodeAbstractResourceInstance: a,
    76  			forceReplace:                 b.ForceReplace,
    77  		}
    78  	}
    79  
    80  	steps := []GraphTransformer{
    81  		// Creates all the resources represented in the config. During apply,
    82  		// we use this just to ensure that the whole-resource metadata is
    83  		// updated to reflect things such as whether the count argument is
    84  		// set in config, or which provider configuration manages each resource.
    85  		&ConfigTransformer{
    86  			Concrete: concreteResource,
    87  			Config:   b.Config,
    88  		},
    89  
    90  		// Add dynamic values
    91  		&RootVariableTransformer{Config: b.Config},
    92  		&ModuleVariableTransformer{Config: b.Config},
    93  		&LocalTransformer{Config: b.Config},
    94  		&OutputTransformer{Config: b.Config, Changes: b.Changes},
    95  
    96  		// Creates all the resource instances represented in the diff, along
    97  		// with dependency edges against the whole-resource nodes added by
    98  		// ConfigTransformer above.
    99  		&DiffTransformer{
   100  			Concrete: concreteResourceInstance,
   101  			State:    b.State,
   102  			Changes:  b.Changes,
   103  		},
   104  
   105  		// Attach the state
   106  		&AttachStateTransformer{State: b.State},
   107  
   108  		// Create orphan output nodes
   109  		&OrphanOutputTransformer{Config: b.Config, State: b.State},
   110  
   111  		// Attach the configuration to any resources
   112  		&AttachResourceConfigTransformer{Config: b.Config},
   113  
   114  		// add providers
   115  		transformProviders(concreteProvider, b.Config),
   116  
   117  		// Remove modules no longer present in the config
   118  		&RemovedModuleTransformer{Config: b.Config, State: b.State},
   119  
   120  		// Must attach schemas before ReferenceTransformer so that we can
   121  		// analyze the configuration to find references.
   122  		&AttachSchemaTransformer{Plugins: b.Plugins, Config: b.Config},
   123  
   124  		// Create expansion nodes for all of the module calls. This must
   125  		// come after all other transformers that create nodes representing
   126  		// objects that can belong to modules.
   127  		&ModuleExpansionTransformer{Config: b.Config},
   128  
   129  		// Connect references so ordering is correct
   130  		&ReferenceTransformer{},
   131  		&AttachDependenciesTransformer{},
   132  
   133  		// Detect when create_before_destroy must be forced on for a particular
   134  		// node due to dependency edges, to avoid graph cycles during apply.
   135  		&ForcedCBDTransformer{},
   136  
   137  		// Destruction ordering
   138  		&DestroyEdgeTransformer{
   139  			Config: b.Config,
   140  			State:  b.State,
   141  		},
   142  		&CBDEdgeTransformer{
   143  			Config: b.Config,
   144  			State:  b.State,
   145  		},
   146  
   147  		// We need to remove configuration nodes that are not used at all, as
   148  		// they may not be able to evaluate, especially during destroy.
   149  		// These include variables, locals, and instance expanders.
   150  		&pruneUnusedNodesTransformer{},
   151  
   152  		// Target
   153  		&TargetsTransformer{Targets: b.Targets},
   154  
   155  		// Close opened plugin connections
   156  		&CloseProviderTransformer{},
   157  
   158  		// close the root module
   159  		&CloseRootModuleTransformer{},
   160  
   161  		// Perform the transitive reduction to make our graph a bit
   162  		// more understandable if possible (it usually is possible).
   163  		&TransitiveReductionTransformer{},
   164  	}
   165  
   166  	return steps
   167  }