github.com/tarrant/terraform@v0.3.8-0.20150402012457-f68c9eee638e/terraform/transform_targets.go (about) 1 package terraform 2 3 import "github.com/hashicorp/terraform/dag" 4 5 // TargetsTransformer is a GraphTransformer that, when the user specifies a 6 // list of resources to target, limits the graph to only those resources and 7 // their dependencies. 8 type TargetsTransformer struct { 9 // List of targeted resource names specified by the user 10 Targets []string 11 12 // Set to true when we're in a `terraform destroy` or a 13 // `terraform plan -destroy` 14 Destroy bool 15 } 16 17 func (t *TargetsTransformer) Transform(g *Graph) error { 18 if len(t.Targets) > 0 { 19 // TODO: duplicated in OrphanTransformer; pull up parsing earlier 20 addrs, err := t.parseTargetAddresses() 21 if err != nil { 22 return err 23 } 24 25 targetedNodes, err := t.selectTargetedNodes(g, addrs) 26 if err != nil { 27 return err 28 } 29 30 for _, v := range g.Vertices() { 31 if targetedNodes.Include(v) { 32 } else { 33 g.Remove(v) 34 } 35 } 36 } 37 return nil 38 } 39 40 func (t *TargetsTransformer) parseTargetAddresses() ([]ResourceAddress, error) { 41 addrs := make([]ResourceAddress, len(t.Targets)) 42 for i, target := range t.Targets { 43 ta, err := ParseResourceAddress(target) 44 if err != nil { 45 return nil, err 46 } 47 addrs[i] = *ta 48 } 49 return addrs, nil 50 } 51 52 func (t *TargetsTransformer) selectTargetedNodes( 53 g *Graph, addrs []ResourceAddress) (*dag.Set, error) { 54 targetedNodes := new(dag.Set) 55 for _, v := range g.Vertices() { 56 // Keep all providers; they'll be pruned later if necessary 57 if r, ok := v.(GraphNodeProvider); ok { 58 targetedNodes.Add(r) 59 continue 60 } 61 62 // For the remaining filter, we only care about addressable nodes 63 r, ok := v.(GraphNodeAddressable) 64 if !ok { 65 continue 66 } 67 68 if t.nodeIsTarget(r, addrs) { 69 targetedNodes.Add(r) 70 // If the node would like to know about targets, tell it. 71 if n, ok := r.(GraphNodeTargetable); ok { 72 n.SetTargets(addrs) 73 } 74 75 var deps *dag.Set 76 var err error 77 if t.Destroy { 78 deps, err = g.Descendents(r) 79 } else { 80 deps, err = g.Ancestors(r) 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 r GraphNodeAddressable, addrs []ResourceAddress) bool { 96 addr := r.ResourceAddress() 97 for _, targetAddr := range addrs { 98 if targetAddr.Equals(addr) { 99 return true 100 } 101 } 102 return false 103 }