6 "github.com/hashicorp/terraform/addrs"
7 "github.com/hashicorp/terraform/dag"
8 "github.com/hashicorp/terraform/states"
11 // OrphanResourceCountTransformer is a GraphTransformer that adds orphans
12 // for an expanded count to the graph. The determination of this depends
13 // on the count argument given.
15 // Orphans are found by comparing the count to what is found in the state.
16 // This transform assumes that if an element in the state is within the count
17 // bounds given, that it is not an orphan.
18 type OrphanResourceCountTransformer struct {
19 Concrete ConcreteResourceInstanceNodeFunc
21 Count int // Actual count of the resource, or -1 if count is not set at all
22 Addr addrs.AbsResource // Addr of the resource to look for orphans
23 State *states.State // Full global state
26 func (t *OrphanResourceCountTransformer) Transform(g *Graph) error {
27 rs := t.State.Resource(t.Addr)
29 return nil // Resource doesn't exist in state, so nothing to do!
32 haveKeys := make(map[addrs.InstanceKey]struct{})
33 for key := range rs.Instances {
34 haveKeys[key] = struct{}{}
38 return t.transformNoCount(haveKeys, g)
41 return t.transformZeroCount(haveKeys, g)
43 return t.transformCount(haveKeys, g)
46 func (t *OrphanResourceCountTransformer) transformCount(haveKeys map[addrs.InstanceKey]struct{}, g *Graph) error {
47 // Due to the logic in Transform, we only get in here if our count is
50 _, have0Key := haveKeys[addrs.IntKey(0)]
52 for key := range haveKeys {
53 if key == addrs.NoKey && !have0Key {
54 // If we have no 0-key then we will accept a no-key instance
55 // as an alias for it.
59 i, isInt := key.(addrs.IntKey)
60 if isInt && int(i) < t.Count {
64 abstract := NewNodeAbstractResourceInstance(t.Addr.Instance(key))
65 var node dag.Vertex = abstract
66 if f := t.Concrete; f != nil {
69 log.Printf("[TRACE] OrphanResourceCount(non-zero): adding %s as %T", t.Addr, node)
76 func (t *OrphanResourceCountTransformer) transformZeroCount(haveKeys map[addrs.InstanceKey]struct{}, g *Graph) error {
77 // This case is easy: we need to orphan any keys we have at all.
79 for key := range haveKeys {
80 abstract := NewNodeAbstractResourceInstance(t.Addr.Instance(key))
81 var node dag.Vertex = abstract
82 if f := t.Concrete; f != nil {
85 log.Printf("[TRACE] OrphanResourceCount(zero): adding %s as %T", t.Addr, node)
92 func (t *OrphanResourceCountTransformer) transformNoCount(haveKeys map[addrs.InstanceKey]struct{}, g *Graph) error {
93 // Negative count indicates that count is not set at all, in which
94 // case we expect to have a single instance with no key set at all.
95 // However, we'll also accept an instance with key 0 set as an alias
96 // for it, in case the user has just deleted the "count" argument and
97 // so wants to keep the first instance in the set.
99 _, haveNoKey := haveKeys[addrs.NoKey]
100 _, have0Key := haveKeys[addrs.IntKey(0)]
101 keepKey := addrs.NoKey
102 if have0Key && !haveNoKey {
103 // If we don't have a no-key instance then we can use the 0-key instance
105 keepKey = addrs.IntKey(0)
108 for key := range haveKeys {
113 abstract := NewNodeAbstractResourceInstance(t.Addr.Instance(key))
114 var node dag.Vertex = abstract
115 if f := t.Concrete; f != nil {
118 log.Printf("[TRACE] OrphanResourceCount(no-count): adding %s as %T", t.Addr, node)