github.com/rliebz/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/terraform/transform_diff.go (about)

     1  package terraform
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  
     7  	"github.com/hashicorp/terraform/config/module"
     8  	"github.com/hashicorp/terraform/dag"
     9  )
    10  
    11  // DiffTransformer is a GraphTransformer that adds the elements of
    12  // the diff to the graph.
    13  //
    14  // This transform is used for example by the ApplyGraphBuilder to ensure
    15  // that only resources that are being modified are represented in the graph.
    16  //
    17  // Module and State is still required for the DiffTransformer for annotations
    18  // since the Diff doesn't contain all the information required to build the
    19  // complete graph (such as create-before-destroy information). The graph
    20  // is built based on the diff first, though, ensuring that only resources
    21  // that are being modified are present in the graph.
    22  type DiffTransformer struct {
    23  	Concrete ConcreteResourceNodeFunc
    24  
    25  	Diff   *Diff
    26  	Module *module.Tree
    27  	State  *State
    28  }
    29  
    30  func (t *DiffTransformer) Transform(g *Graph) error {
    31  	// If the diff is nil or empty (nil is empty) then do nothing
    32  	if t.Diff.Empty() {
    33  		return nil
    34  	}
    35  
    36  	// Go through all the modules in the diff.
    37  	log.Printf("[TRACE] DiffTransformer: starting")
    38  	var nodes []dag.Vertex
    39  	for _, m := range t.Diff.Modules {
    40  		log.Printf("[TRACE] DiffTransformer: Module: %s", m)
    41  		// TODO: If this is a destroy diff then add a module destroy node
    42  
    43  		// Go through all the resources in this module.
    44  		for name, inst := range m.Resources {
    45  			log.Printf("[TRACE] DiffTransformer: Resource %q: %#v", name, inst)
    46  
    47  			// We have changes! This is a create or update operation.
    48  			// First grab the address so we have a unique way to
    49  			// reference this resource.
    50  			addr, err := parseResourceAddressInternal(name)
    51  			if err != nil {
    52  				panic(fmt.Sprintf(
    53  					"Error parsing internal name, this is a bug: %q", name))
    54  			}
    55  
    56  			// Very important: add the module path for this resource to
    57  			// the address. Remove "root" from it.
    58  			addr.Path = m.Path[1:]
    59  
    60  			// If we're destroying, add the destroy node
    61  			if inst.Destroy || inst.GetDestroyDeposed() {
    62  				abstract := &NodeAbstractResource{Addr: addr}
    63  				g.Add(&NodeDestroyResource{NodeAbstractResource: abstract})
    64  			}
    65  
    66  			// If we have changes, then add the applyable version
    67  			if len(inst.Attributes) > 0 {
    68  				// Add the resource to the graph
    69  				abstract := &NodeAbstractResource{Addr: addr}
    70  				var node dag.Vertex = abstract
    71  				if f := t.Concrete; f != nil {
    72  					node = f(abstract)
    73  				}
    74  
    75  				nodes = append(nodes, node)
    76  			}
    77  		}
    78  	}
    79  
    80  	// Add all the nodes to the graph
    81  	for _, n := range nodes {
    82  		g.Add(n)
    83  	}
    84  
    85  	return nil
    86  }