7 "github.com/hashicorp/terraform/addrs"
8 "github.com/hashicorp/terraform/states"
11 // ChangesSync is a wrapper around a Changes that provides a concurrency-safe
12 // interface to insert new changes and retrieve copies of existing changes.
14 // Each ChangesSync is independent of all others, so all concurrent writers
15 // to a particular Changes must share a single ChangesSync. Behavior is
16 // undefined if any other caller makes changes to the underlying Changes
17 // object or its nested objects concurrently with any of the methods of a
18 // particular ChangesSync.
19 type ChangesSync struct {
24 // AppendResourceInstanceChange records the given resource instance change in
25 // the set of planned resource changes.
27 // The caller must ensure that there are no concurrent writes to the given
28 // change while this method is running, but it is safe to resume mutating
29 // it after this method returns without affecting the saved change.
30 func (cs *ChangesSync) AppendResourceInstanceChange(changeSrc *ResourceInstanceChangeSrc) {
32 panic("AppendResourceInstanceChange on nil ChangesSync")
35 defer cs.lock.Unlock()
37 s := changeSrc.DeepCopy()
38 cs.changes.Resources = append(cs.changes.Resources, s)
41 // GetResourceInstanceChange searches the set of resource instance changes for
42 // one matching the given address and generation, returning it if it exists.
44 // If no such change exists, nil is returned.
46 // The returned object is a deep copy of the change recorded in the plan, so
47 // callers may mutate it although it's generally better (less confusing) to
48 // treat planned changes as immutable after they've been initially constructed.
49 func (cs *ChangesSync) GetResourceInstanceChange(addr addrs.AbsResourceInstance, gen states.Generation) *ResourceInstanceChangeSrc {
51 panic("GetResourceInstanceChange on nil ChangesSync")
54 defer cs.lock.Unlock()
56 if gen == states.CurrentGen {
57 return cs.changes.ResourceInstance(addr).DeepCopy()
59 if dk, ok := gen.(states.DeposedKey); ok {
60 return cs.changes.ResourceInstanceDeposed(addr, dk).DeepCopy()
62 panic(fmt.Sprintf("unsupported generation value %#v", gen))
65 // RemoveResourceInstanceChange searches the set of resource instance changes
66 // for one matching the given address and generation, and removes it from the
68 func (cs *ChangesSync) RemoveResourceInstanceChange(addr addrs.AbsResourceInstance, gen states.Generation) {
70 panic("RemoveResourceInstanceChange on nil ChangesSync")
73 defer cs.lock.Unlock()
75 dk := states.NotDeposed
76 if realDK, ok := gen.(states.DeposedKey); ok {
80 addrStr := addr.String()
81 for i, r := range cs.changes.Resources {
82 if r.Addr.String() != addrStr || r.DeposedKey != dk {
85 copy(cs.changes.Resources[i:], cs.changes.Resources[i+1:])
86 cs.changes.Resources = cs.changes.Resources[:len(cs.changes.Resources)-1]
91 // AppendOutputChange records the given output value change in the set of
92 // planned value changes.
94 // The caller must ensure that there are no concurrent writes to the given
95 // change while this method is running, but it is safe to resume mutating
96 // it after this method returns without affecting the saved change.
97 func (cs *ChangesSync) AppendOutputChange(changeSrc *OutputChangeSrc) {
99 panic("AppendOutputChange on nil ChangesSync")
102 defer cs.lock.Unlock()
104 s := changeSrc.DeepCopy()
105 cs.changes.Outputs = append(cs.changes.Outputs, s)
108 // GetOutputChange searches the set of output value changes for one matching
109 // the given address, returning it if it exists.
111 // If no such change exists, nil is returned.
113 // The returned object is a deep copy of the change recorded in the plan, so
114 // callers may mutate it although it's generally better (less confusing) to
115 // treat planned changes as immutable after they've been initially constructed.
116 func (cs *ChangesSync) GetOutputChange(addr addrs.AbsOutputValue) *OutputChangeSrc {
118 panic("GetOutputChange on nil ChangesSync")
121 defer cs.lock.Unlock()
123 return cs.changes.OutputValue(addr)
126 // RemoveOutputChange searches the set of output value changes for one matching
127 // the given address, and removes it from the set if it exists.
128 func (cs *ChangesSync) RemoveOutputChange(addr addrs.AbsOutputValue) {
130 panic("RemoveOutputChange on nil ChangesSync")
133 defer cs.lock.Unlock()
135 addrStr := addr.String()
136 for i, o := range cs.changes.Outputs {
137 if o.Addr.String() != addrStr {
140 copy(cs.changes.Outputs[i:], cs.changes.Outputs[i+1:])
141 cs.changes.Outputs = cs.changes.Outputs[:len(cs.changes.Outputs)-1]