github.com/hooklift/terraform@v0.11.0-beta1.0.20171117000744-6786c1361ffe/terraform/graph_builder_refresh.go (about)

     1  package terraform
     2  
     3  import (
     4  	"log"
     5  
     6  	"github.com/hashicorp/terraform/config"
     7  	"github.com/hashicorp/terraform/config/module"
     8  	"github.com/hashicorp/terraform/dag"
     9  )
    10  
    11  // RefreshGraphBuilder implements GraphBuilder and is responsible for building
    12  // a graph for refreshing (updating the Terraform state).
    13  //
    14  // The primary difference between this graph and others:
    15  //
    16  //   * Based on the state since it represents the only resources that
    17  //     need to be refreshed.
    18  //
    19  //   * Ignores lifecycle options since no lifecycle events occur here. This
    20  //     simplifies the graph significantly since complex transforms such as
    21  //     create-before-destroy can be completely ignored.
    22  //
    23  type RefreshGraphBuilder struct {
    24  	// Module is the root module for the graph to build.
    25  	Module *module.Tree
    26  
    27  	// State is the current state
    28  	State *State
    29  
    30  	// Providers is the list of providers supported.
    31  	Providers []string
    32  
    33  	// Targets are resources to target
    34  	Targets []string
    35  
    36  	// DisableReduce, if true, will not reduce the graph. Great for testing.
    37  	DisableReduce bool
    38  
    39  	// Validate will do structural validation of the graph.
    40  	Validate bool
    41  }
    42  
    43  // See GraphBuilder
    44  func (b *RefreshGraphBuilder) Build(path []string) (*Graph, error) {
    45  	return (&BasicGraphBuilder{
    46  		Steps:    b.Steps(),
    47  		Validate: b.Validate,
    48  		Name:     "RefreshGraphBuilder",
    49  	}).Build(path)
    50  }
    51  
    52  // See GraphBuilder
    53  func (b *RefreshGraphBuilder) Steps() []GraphTransformer {
    54  	// Custom factory for creating providers.
    55  	concreteProvider := func(a *NodeAbstractProvider) dag.Vertex {
    56  		return &NodeApplyableProvider{
    57  			NodeAbstractProvider: a,
    58  		}
    59  	}
    60  
    61  	concreteManagedResource := func(a *NodeAbstractResource) dag.Vertex {
    62  		return &NodeRefreshableManagedResource{
    63  			NodeAbstractCountResource: &NodeAbstractCountResource{
    64  				NodeAbstractResource: a,
    65  			},
    66  		}
    67  	}
    68  
    69  	concreteManagedResourceInstance := func(a *NodeAbstractResource) dag.Vertex {
    70  		return &NodeRefreshableManagedResourceInstance{
    71  			NodeAbstractResource: a,
    72  		}
    73  	}
    74  
    75  	concreteDataResource := func(a *NodeAbstractResource) dag.Vertex {
    76  		return &NodeRefreshableDataResource{
    77  			NodeAbstractCountResource: &NodeAbstractCountResource{
    78  				NodeAbstractResource: a,
    79  			},
    80  		}
    81  	}
    82  
    83  	steps := []GraphTransformer{
    84  		// Creates all the managed resources that aren't in the state, but only if
    85  		// we have a state already. No resources in state means there's not
    86  		// anything to refresh.
    87  		func() GraphTransformer {
    88  			if b.State.HasResources() {
    89  				return &ConfigTransformer{
    90  					Concrete:   concreteManagedResource,
    91  					Module:     b.Module,
    92  					Unique:     true,
    93  					ModeFilter: true,
    94  					Mode:       config.ManagedResourceMode,
    95  				}
    96  			}
    97  			log.Println("[TRACE] No managed resources in state during refresh, skipping managed resource transformer")
    98  			return nil
    99  		}(),
   100  
   101  		// Creates all the data resources that aren't in the state. This will also
   102  		// add any orphans from scaling in as destroy nodes.
   103  		&ConfigTransformer{
   104  			Concrete:   concreteDataResource,
   105  			Module:     b.Module,
   106  			Unique:     true,
   107  			ModeFilter: true,
   108  			Mode:       config.DataResourceMode,
   109  		},
   110  
   111  		// Add any fully-orphaned resources from config (ones that have been
   112  		// removed completely, not ones that are just orphaned due to a scaled-in
   113  		// count.
   114  		&OrphanResourceTransformer{
   115  			Concrete: concreteManagedResourceInstance,
   116  			State:    b.State,
   117  			Module:   b.Module,
   118  		},
   119  
   120  		// Attach the state
   121  		&AttachStateTransformer{State: b.State},
   122  
   123  		// Attach the configuration to any resources
   124  		&AttachResourceConfigTransformer{Module: b.Module},
   125  
   126  		// Add root variables
   127  		&RootVariableTransformer{Module: b.Module},
   128  
   129  		TransformProviders(b.Providers, concreteProvider, b.Module),
   130  
   131  		// Add the local values
   132  		&LocalTransformer{Module: b.Module},
   133  
   134  		// Add the outputs
   135  		&OutputTransformer{Module: b.Module},
   136  
   137  		// Add module variables
   138  		&ModuleVariableTransformer{Module: b.Module},
   139  
   140  		// Connect so that the references are ready for targeting. We'll
   141  		// have to connect again later for providers and so on.
   142  		&ReferenceTransformer{},
   143  
   144  		// Target
   145  		&TargetsTransformer{
   146  			Targets: b.Targets,
   147  
   148  			// Resource nodes from config have not yet been expanded for
   149  			// "count", so we must apply targeting without indices. Exact
   150  			// targeting will be dealt with later when these resources
   151  			// DynamicExpand.
   152  			IgnoreIndices: true,
   153  		},
   154  
   155  		// Close opened plugin connections
   156  		&CloseProviderTransformer{},
   157  
   158  		// Single root
   159  		&RootTransformer{},
   160  	}
   161  
   162  	if !b.DisableReduce {
   163  		// Perform the transitive reduction to make our graph a bit
   164  		// more sane if possible (it usually is possible).
   165  		steps = append(steps, &TransitiveReductionTransformer{})
   166  	}
   167  
   168  	return steps
   169  }