]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/hashicorp/terraform/plans/changes_sync.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / plans / changes_sync.go
1 package plans
2
3 import (
4 "fmt"
5 "sync"
6
7 "github.com/hashicorp/terraform/addrs"
8 "github.com/hashicorp/terraform/states"
9 )
10
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.
13 //
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 {
20 lock sync.Mutex
21 changes *Changes
22 }
23
24 // AppendResourceInstanceChange records the given resource instance change in
25 // the set of planned resource changes.
26 //
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) {
31 if cs == nil {
32 panic("AppendResourceInstanceChange on nil ChangesSync")
33 }
34 cs.lock.Lock()
35 defer cs.lock.Unlock()
36
37 s := changeSrc.DeepCopy()
38 cs.changes.Resources = append(cs.changes.Resources, s)
39 }
40
41 // GetResourceInstanceChange searches the set of resource instance changes for
42 // one matching the given address and generation, returning it if it exists.
43 //
44 // If no such change exists, nil is returned.
45 //
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 {
50 if cs == nil {
51 panic("GetResourceInstanceChange on nil ChangesSync")
52 }
53 cs.lock.Lock()
54 defer cs.lock.Unlock()
55
56 if gen == states.CurrentGen {
57 return cs.changes.ResourceInstance(addr).DeepCopy()
58 }
59 if dk, ok := gen.(states.DeposedKey); ok {
60 return cs.changes.ResourceInstanceDeposed(addr, dk).DeepCopy()
61 }
62 panic(fmt.Sprintf("unsupported generation value %#v", gen))
63 }
64
65 // RemoveResourceInstanceChange searches the set of resource instance changes
66 // for one matching the given address and generation, and removes it from the
67 // set if it exists.
68 func (cs *ChangesSync) RemoveResourceInstanceChange(addr addrs.AbsResourceInstance, gen states.Generation) {
69 if cs == nil {
70 panic("RemoveResourceInstanceChange on nil ChangesSync")
71 }
72 cs.lock.Lock()
73 defer cs.lock.Unlock()
74
75 dk := states.NotDeposed
76 if realDK, ok := gen.(states.DeposedKey); ok {
77 dk = realDK
78 }
79
80 addrStr := addr.String()
81 for i, r := range cs.changes.Resources {
82 if r.Addr.String() != addrStr || r.DeposedKey != dk {
83 continue
84 }
85 copy(cs.changes.Resources[i:], cs.changes.Resources[i+1:])
86 cs.changes.Resources = cs.changes.Resources[:len(cs.changes.Resources)-1]
87 return
88 }
89 }
90
91 // AppendOutputChange records the given output value change in the set of
92 // planned value changes.
93 //
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) {
98 if cs == nil {
99 panic("AppendOutputChange on nil ChangesSync")
100 }
101 cs.lock.Lock()
102 defer cs.lock.Unlock()
103
104 s := changeSrc.DeepCopy()
105 cs.changes.Outputs = append(cs.changes.Outputs, s)
106 }
107
108 // GetOutputChange searches the set of output value changes for one matching
109 // the given address, returning it if it exists.
110 //
111 // If no such change exists, nil is returned.
112 //
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 {
117 if cs == nil {
118 panic("GetOutputChange on nil ChangesSync")
119 }
120 cs.lock.Lock()
121 defer cs.lock.Unlock()
122
123 return cs.changes.OutputValue(addr)
124 }
125
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) {
129 if cs == nil {
130 panic("RemoveOutputChange on nil ChangesSync")
131 }
132 cs.lock.Lock()
133 defer cs.lock.Unlock()
134
135 addrStr := addr.String()
136 for i, o := range cs.changes.Outputs {
137 if o.Addr.String() != addrStr {
138 continue
139 }
140 copy(cs.changes.Outputs[i:], cs.changes.Outputs[i+1:])
141 cs.changes.Outputs = cs.changes.Outputs[:len(cs.changes.Outputs)-1]
142 return
143 }
144 }