github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/terraform/transform_targets.go (about) 1 package terraform 2 3 import ( 4 "log" 5 6 "github.com/hashicorp/terraform/dag" 7 ) 8 9 // TargetsTransformer is a GraphTransformer that, when the user specifies a 10 // list of resources to target, limits the graph to only those resources and 11 // their dependencies. 12 type TargetsTransformer struct { 13 // List of targeted resource names specified by the user 14 Targets []string 15 16 // Set to true when we're in a `terraform destroy` or a 17 // `terraform plan -destroy` 18 Destroy bool 19 } 20 21 func (t *TargetsTransformer) Transform(g *Graph) error { 22 if len(t.Targets) > 0 { 23 // TODO: duplicated in OrphanTransformer; pull up parsing earlier 24 addrs, err := t.parseTargetAddresses() 25 if err != nil { 26 return err 27 } 28 29 targetedNodes, err := t.selectTargetedNodes(g, addrs) 30 if err != nil { 31 return err 32 } 33 34 for _, v := range g.Vertices() { 35 if _, ok := v.(GraphNodeAddressable); ok { 36 if !targetedNodes.Include(v) { 37 log.Printf("[DEBUG] Removing %q, filtered by targeting.", dag.VertexName(v)) 38 g.Remove(v) 39 } 40 } 41 } 42 } 43 return nil 44 } 45 46 func (t *TargetsTransformer) parseTargetAddresses() ([]ResourceAddress, error) { 47 addrs := make([]ResourceAddress, len(t.Targets)) 48 for i, target := range t.Targets { 49 ta, err := ParseResourceAddress(target) 50 if err != nil { 51 return nil, err 52 } 53 addrs[i] = *ta 54 } 55 return addrs, nil 56 } 57 58 // Returns the list of targeted nodes. A targeted node is either addressed 59 // directly, or is an Ancestor of a targeted node. Destroy mode keeps 60 // Descendents instead of Ancestors. 61 func (t *TargetsTransformer) selectTargetedNodes( 62 g *Graph, addrs []ResourceAddress) (*dag.Set, error) { 63 targetedNodes := new(dag.Set) 64 for _, v := range g.Vertices() { 65 if t.nodeIsTarget(v, addrs) { 66 targetedNodes.Add(v) 67 68 // We inform nodes that ask about the list of targets - helps for nodes 69 // that need to dynamically expand. Note that this only occurs for nodes 70 // that are already directly targeted. 71 if tn, ok := v.(GraphNodeTargetable); ok { 72 tn.SetTargets(addrs) 73 } 74 75 var deps *dag.Set 76 var err error 77 if t.Destroy { 78 deps, err = g.Descendents(v) 79 } else { 80 deps, err = g.Ancestors(v) 81 } 82 if err != nil { 83 return nil, err 84 } 85 86 for _, d := range deps.List() { 87 targetedNodes.Add(d) 88 } 89 } 90 } 91 return targetedNodes, nil 92 } 93 94 func (t *TargetsTransformer) nodeIsTarget( 95 v dag.Vertex, addrs []ResourceAddress) bool { 96 r, ok := v.(GraphNodeAddressable) 97 if !ok { 98 return false 99 } 100 addr := r.ResourceAddress() 101 for _, targetAddr := range addrs { 102 if targetAddr.Equals(addr) { 103 return true 104 } 105 } 106 return false 107 }