github.com/skyscape-cloud-services/terraform@v0.9.2-0.20170609144644-7ece028a1747/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  		// Create all the providers
   130  		&MissingProviderTransformer{Providers: b.Providers, Concrete: concreteProvider},
   131  		&ProviderTransformer{},
   132  		&DisableProviderTransformer{},
   133  		&ParentProviderTransformer{},
   134  		&AttachProviderConfigTransformer{Module: b.Module},
   135  
   136  		// Add the outputs
   137  		&OutputTransformer{Module: b.Module},
   138  
   139  		// Add module variables
   140  		&ModuleVariableTransformer{Module: b.Module},
   141  
   142  		// Connect so that the references are ready for targeting. We'll
   143  		// have to connect again later for providers and so on.
   144  		&ReferenceTransformer{},
   145  
   146  		// Target
   147  		&TargetsTransformer{Targets: b.Targets},
   148  
   149  		// Close opened plugin connections
   150  		&CloseProviderTransformer{},
   151  
   152  		// Single root
   153  		&RootTransformer{},
   154  	}
   155  
   156  	if !b.DisableReduce {
   157  		// Perform the transitive reduction to make our graph a bit
   158  		// more sane if possible (it usually is possible).
   159  		steps = append(steps, &TransitiveReductionTransformer{})
   160  	}
   161  
   162  	return steps
   163  }