aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/terraform/addrs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/addrs')
-rw-r--r--vendor/github.com/hashicorp/terraform/addrs/count_attr.go12
-rw-r--r--vendor/github.com/hashicorp/terraform/addrs/doc.go17
-rw-r--r--vendor/github.com/hashicorp/terraform/addrs/input_variable.go41
-rw-r--r--vendor/github.com/hashicorp/terraform/addrs/instance_key.go123
-rw-r--r--vendor/github.com/hashicorp/terraform/addrs/local_value.go48
-rw-r--r--vendor/github.com/hashicorp/terraform/addrs/module.go75
-rw-r--r--vendor/github.com/hashicorp/terraform/addrs/module_call.go81
-rw-r--r--vendor/github.com/hashicorp/terraform/addrs/module_instance.go415
-rw-r--r--vendor/github.com/hashicorp/terraform/addrs/output_value.go75
-rw-r--r--vendor/github.com/hashicorp/terraform/addrs/parse_ref.go338
-rw-r--r--vendor/github.com/hashicorp/terraform/addrs/parse_target.go318
-rw-r--r--vendor/github.com/hashicorp/terraform/addrs/path_attr.go12
-rw-r--r--vendor/github.com/hashicorp/terraform/addrs/provider_config.go297
-rw-r--r--vendor/github.com/hashicorp/terraform/addrs/referenceable.go20
-rw-r--r--vendor/github.com/hashicorp/terraform/addrs/resource.go270
-rw-r--r--vendor/github.com/hashicorp/terraform/addrs/resource_phase.go105
-rw-r--r--vendor/github.com/hashicorp/terraform/addrs/resourcemode_string.go33
-rw-r--r--vendor/github.com/hashicorp/terraform/addrs/self.go14
-rw-r--r--vendor/github.com/hashicorp/terraform/addrs/targetable.go26
-rw-r--r--vendor/github.com/hashicorp/terraform/addrs/terraform_attr.go12
20 files changed, 2332 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/addrs/count_attr.go b/vendor/github.com/hashicorp/terraform/addrs/count_attr.go
new file mode 100644
index 0000000..90a5faf
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/addrs/count_attr.go
@@ -0,0 +1,12 @@
1package addrs
2
3// CountAttr is the address of an attribute of the "count" object in
4// the interpolation scope, like "count.index".
5type CountAttr struct {
6 referenceable
7 Name string
8}
9
10func (ca CountAttr) String() string {
11 return "count." + ca.Name
12}
diff --git a/vendor/github.com/hashicorp/terraform/addrs/doc.go b/vendor/github.com/hashicorp/terraform/addrs/doc.go
new file mode 100644
index 0000000..4609331
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/addrs/doc.go
@@ -0,0 +1,17 @@
1// Package addrs contains types that represent "addresses", which are
2// references to specific objects within a Terraform configuration or
3// state.
4//
5// All addresses have string representations based on HCL traversal syntax
6// which should be used in the user-interface, and also in-memory
7// representations that can be used internally.
8//
9// For object types that exist within Terraform modules a pair of types is
10// used. The "local" part of the address is represented by a type, and then
11// an absolute path to that object in the context of its module is represented
12// by a type of the same name with an "Abs" prefix added, for "absolute".
13//
14// All types within this package should be treated as immutable, even if this
15// is not enforced by the Go compiler. It is always an implementation error
16// to modify an address object in-place after it is initially constructed.
17package addrs
diff --git a/vendor/github.com/hashicorp/terraform/addrs/input_variable.go b/vendor/github.com/hashicorp/terraform/addrs/input_variable.go
new file mode 100644
index 0000000..d2c046c
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/addrs/input_variable.go
@@ -0,0 +1,41 @@
1package addrs
2
3import (
4 "fmt"
5)
6
7// InputVariable is the address of an input variable.
8type InputVariable struct {
9 referenceable
10 Name string
11}
12
13func (v InputVariable) String() string {
14 return "var." + v.Name
15}
16
17// AbsInputVariableInstance is the address of an input variable within a
18// particular module instance.
19type AbsInputVariableInstance struct {
20 Module ModuleInstance
21 Variable InputVariable
22}
23
24// InputVariable returns the absolute address of the input variable of the
25// given name inside the receiving module instance.
26func (m ModuleInstance) InputVariable(name string) AbsInputVariableInstance {
27 return AbsInputVariableInstance{
28 Module: m,
29 Variable: InputVariable{
30 Name: name,
31 },
32 }
33}
34
35func (v AbsInputVariableInstance) String() string {
36 if len(v.Module) == 0 {
37 return v.String()
38 }
39
40 return fmt.Sprintf("%s.%s", v.Module.String(), v.Variable.String())
41}
diff --git a/vendor/github.com/hashicorp/terraform/addrs/instance_key.go b/vendor/github.com/hashicorp/terraform/addrs/instance_key.go
new file mode 100644
index 0000000..cef8b27
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/addrs/instance_key.go
@@ -0,0 +1,123 @@
1package addrs
2
3import (
4 "fmt"
5
6 "github.com/zclconf/go-cty/cty"
7 "github.com/zclconf/go-cty/cty/gocty"
8)
9
10// InstanceKey represents the key of an instance within an object that
11// contains multiple instances due to using "count" or "for_each" arguments
12// in configuration.
13//
14// IntKey and StringKey are the two implementations of this type. No other
15// implementations are allowed. The single instance of an object that _isn't_
16// using "count" or "for_each" is represented by NoKey, which is a nil
17// InstanceKey.
18type InstanceKey interface {
19 instanceKeySigil()
20 String() string
21}
22
23// ParseInstanceKey returns the instance key corresponding to the given value,
24// which must be known and non-null.
25//
26// If an unknown or null value is provided then this function will panic. This
27// function is intended to deal with the values that would naturally be found
28// in a hcl.TraverseIndex, which (when parsed from source, at least) can never
29// contain unknown or null values.
30func ParseInstanceKey(key cty.Value) (InstanceKey, error) {
31 switch key.Type() {
32 case cty.String:
33 return StringKey(key.AsString()), nil
34 case cty.Number:
35 var idx int
36 err := gocty.FromCtyValue(key, &idx)
37 return IntKey(idx), err
38 default:
39 return NoKey, fmt.Errorf("either a string or an integer is required")
40 }
41}
42
43// NoKey represents the absense of an InstanceKey, for the single instance
44// of a configuration object that does not use "count" or "for_each" at all.
45var NoKey InstanceKey
46
47// IntKey is the InstanceKey representation representing integer indices, as
48// used when the "count" argument is specified or if for_each is used with
49// a sequence type.
50type IntKey int
51
52func (k IntKey) instanceKeySigil() {
53}
54
55func (k IntKey) String() string {
56 return fmt.Sprintf("[%d]", int(k))
57}
58
59// StringKey is the InstanceKey representation representing string indices, as
60// used when the "for_each" argument is specified with a map or object type.
61type StringKey string
62
63func (k StringKey) instanceKeySigil() {
64}
65
66func (k StringKey) String() string {
67 // FIXME: This isn't _quite_ right because Go's quoted string syntax is
68 // slightly different than HCL's, but we'll accept it for now.
69 return fmt.Sprintf("[%q]", string(k))
70}
71
72// InstanceKeyLess returns true if the first given instance key i should sort
73// before the second key j, and false otherwise.
74func InstanceKeyLess(i, j InstanceKey) bool {
75 iTy := instanceKeyType(i)
76 jTy := instanceKeyType(j)
77
78 switch {
79 case i == j:
80 return false
81 case i == NoKey:
82 return true
83 case j == NoKey:
84 return false
85 case iTy != jTy:
86 // The ordering here is arbitrary except that we want NoKeyType
87 // to sort before the others, so we'll just use the enum values
88 // of InstanceKeyType here (where NoKey is zero, sorting before
89 // any other).
90 return uint32(iTy) < uint32(jTy)
91 case iTy == IntKeyType:
92 return int(i.(IntKey)) < int(j.(IntKey))
93 case iTy == StringKeyType:
94 return string(i.(StringKey)) < string(j.(StringKey))
95 default:
96 // Shouldn't be possible to get down here in practice, since the
97 // above is exhaustive.
98 return false
99 }
100}
101
102func instanceKeyType(k InstanceKey) InstanceKeyType {
103 if _, ok := k.(StringKey); ok {
104 return StringKeyType
105 }
106 if _, ok := k.(IntKey); ok {
107 return IntKeyType
108 }
109 return NoKeyType
110}
111
112// InstanceKeyType represents the different types of instance key that are
113// supported. Usually it is sufficient to simply type-assert an InstanceKey
114// value to either IntKey or StringKey, but this type and its values can be
115// used to represent the types themselves, rather than specific values
116// of those types.
117type InstanceKeyType rune
118
119const (
120 NoKeyType InstanceKeyType = 0
121 IntKeyType InstanceKeyType = 'I'
122 StringKeyType InstanceKeyType = 'S'
123)
diff --git a/vendor/github.com/hashicorp/terraform/addrs/local_value.go b/vendor/github.com/hashicorp/terraform/addrs/local_value.go
new file mode 100644
index 0000000..61a07b9
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/addrs/local_value.go
@@ -0,0 +1,48 @@
1package addrs
2
3import (
4 "fmt"
5)
6
7// LocalValue is the address of a local value.
8type LocalValue struct {
9 referenceable
10 Name string
11}
12
13func (v LocalValue) String() string {
14 return "local." + v.Name
15}
16
17// Absolute converts the receiver into an absolute address within the given
18// module instance.
19func (v LocalValue) Absolute(m ModuleInstance) AbsLocalValue {
20 return AbsLocalValue{
21 Module: m,
22 LocalValue: v,
23 }
24}
25
26// AbsLocalValue is the absolute address of a local value within a module instance.
27type AbsLocalValue struct {
28 Module ModuleInstance
29 LocalValue LocalValue
30}
31
32// LocalValue returns the absolute address of a local value of the given
33// name within the receiving module instance.
34func (m ModuleInstance) LocalValue(name string) AbsLocalValue {
35 return AbsLocalValue{
36 Module: m,
37 LocalValue: LocalValue{
38 Name: name,
39 },
40 }
41}
42
43func (v AbsLocalValue) String() string {
44 if len(v.Module) == 0 {
45 return v.LocalValue.String()
46 }
47 return fmt.Sprintf("%s.%s", v.Module.String(), v.LocalValue.String())
48}
diff --git a/vendor/github.com/hashicorp/terraform/addrs/module.go b/vendor/github.com/hashicorp/terraform/addrs/module.go
new file mode 100644
index 0000000..6420c63
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/addrs/module.go
@@ -0,0 +1,75 @@
1package addrs
2
3import (
4 "strings"
5)
6
7// Module is an address for a module call within configuration. This is
8// the static counterpart of ModuleInstance, representing a traversal through
9// the static module call tree in configuration and does not take into account
10// the potentially-multiple instances of a module that might be created by
11// "count" and "for_each" arguments within those calls.
12//
13// This type should be used only in very specialized cases when working with
14// the static module call tree. Type ModuleInstance is appropriate in more cases.
15//
16// Although Module is a slice, it should be treated as immutable after creation.
17type Module []string
18
19// RootModule is the module address representing the root of the static module
20// call tree, which is also the zero value of Module.
21//
22// Note that this is not the root of the dynamic module tree, which is instead
23// represented by RootModuleInstance.
24var RootModule Module
25
26// IsRoot returns true if the receiver is the address of the root module,
27// or false otherwise.
28func (m Module) IsRoot() bool {
29 return len(m) == 0
30}
31
32func (m Module) String() string {
33 if len(m) == 0 {
34 return ""
35 }
36 return strings.Join([]string(m), ".")
37}
38
39// Child returns the address of a child call in the receiver, identified by the
40// given name.
41func (m Module) Child(name string) Module {
42 ret := make(Module, 0, len(m)+1)
43 ret = append(ret, m...)
44 return append(ret, name)
45}
46
47// Parent returns the address of the parent module of the receiver, or the
48// receiver itself if there is no parent (if it's the root module address).
49func (m Module) Parent() Module {
50 if len(m) == 0 {
51 return m
52 }
53 return m[:len(m)-1]
54}
55
56// Call returns the module call address that corresponds to the given module
57// instance, along with the address of the module that contains it.
58//
59// There is no call for the root module, so this method will panic if called
60// on the root module address.
61//
62// In practice, this just turns the last element of the receiver into a
63// ModuleCall and then returns a slice of the receiever that excludes that
64// last part. This is just a convenience for situations where a call address
65// is required, such as when dealing with *Reference and Referencable values.
66func (m Module) Call() (Module, ModuleCall) {
67 if len(m) == 0 {
68 panic("cannot produce ModuleCall for root module")
69 }
70
71 caller, callName := m[:len(m)-1], m[len(m)-1]
72 return caller, ModuleCall{
73 Name: callName,
74 }
75}
diff --git a/vendor/github.com/hashicorp/terraform/addrs/module_call.go b/vendor/github.com/hashicorp/terraform/addrs/module_call.go
new file mode 100644
index 0000000..09596cc
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/addrs/module_call.go
@@ -0,0 +1,81 @@
1package addrs
2
3import (
4 "fmt"
5)
6
7// ModuleCall is the address of a call from the current module to a child
8// module.
9//
10// There is no "Abs" version of ModuleCall because an absolute module path
11// is represented by ModuleInstance.
12type ModuleCall struct {
13 referenceable
14 Name string
15}
16
17func (c ModuleCall) String() string {
18 return "module." + c.Name
19}
20
21// Instance returns the address of an instance of the receiver identified by
22// the given key.
23func (c ModuleCall) Instance(key InstanceKey) ModuleCallInstance {
24 return ModuleCallInstance{
25 Call: c,
26 Key: key,
27 }
28}
29
30// ModuleCallInstance is the address of one instance of a module created from
31// a module call, which might create multiple instances using "count" or
32// "for_each" arguments.
33type ModuleCallInstance struct {
34 referenceable
35 Call ModuleCall
36 Key InstanceKey
37}
38
39func (c ModuleCallInstance) String() string {
40 if c.Key == NoKey {
41 return c.Call.String()
42 }
43 return fmt.Sprintf("module.%s%s", c.Call.Name, c.Key)
44}
45
46// ModuleInstance returns the address of the module instance that corresponds
47// to the receiving call instance when resolved in the given calling module.
48// In other words, it returns the child module instance that the receving
49// call instance creates.
50func (c ModuleCallInstance) ModuleInstance(caller ModuleInstance) ModuleInstance {
51 return caller.Child(c.Call.Name, c.Key)
52}
53
54// Output returns the address of an output of the receiver identified by its
55// name.
56func (c ModuleCallInstance) Output(name string) ModuleCallOutput {
57 return ModuleCallOutput{
58 Call: c,
59 Name: name,
60 }
61}
62
63// ModuleCallOutput is the address of a particular named output produced by
64// an instance of a module call.
65type ModuleCallOutput struct {
66 referenceable
67 Call ModuleCallInstance
68 Name string
69}
70
71func (co ModuleCallOutput) String() string {
72 return fmt.Sprintf("%s.%s", co.Call.String(), co.Name)
73}
74
75// AbsOutputValue returns the absolute output value address that corresponds
76// to the receving module call output address, once resolved in the given
77// calling module.
78func (co ModuleCallOutput) AbsOutputValue(caller ModuleInstance) AbsOutputValue {
79 moduleAddr := co.Call.ModuleInstance(caller)
80 return moduleAddr.OutputValue(co.Name)
81}
diff --git a/vendor/github.com/hashicorp/terraform/addrs/module_instance.go b/vendor/github.com/hashicorp/terraform/addrs/module_instance.go
new file mode 100644
index 0000000..67e73e5
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/addrs/module_instance.go
@@ -0,0 +1,415 @@
1package addrs
2
3import (
4 "bytes"
5 "fmt"
6
7 "github.com/hashicorp/hcl2/hcl"
8 "github.com/hashicorp/hcl2/hcl/hclsyntax"
9 "github.com/zclconf/go-cty/cty"
10 "github.com/zclconf/go-cty/cty/gocty"
11
12 "github.com/hashicorp/terraform/tfdiags"
13)
14
15// ModuleInstance is an address for a particular module instance within the
16// dynamic module tree. This is an extension of the static traversals
17// represented by type Module that deals with the possibility of a single
18// module call producing multiple instances via the "count" and "for_each"
19// arguments.
20//
21// Although ModuleInstance is a slice, it should be treated as immutable after
22// creation.
23type ModuleInstance []ModuleInstanceStep
24
25var (
26 _ Targetable = ModuleInstance(nil)
27)
28
29func ParseModuleInstance(traversal hcl.Traversal) (ModuleInstance, tfdiags.Diagnostics) {
30 mi, remain, diags := parseModuleInstancePrefix(traversal)
31 if len(remain) != 0 {
32 if len(remain) == len(traversal) {
33 diags = diags.Append(&hcl.Diagnostic{
34 Severity: hcl.DiagError,
35 Summary: "Invalid module instance address",
36 Detail: "A module instance address must begin with \"module.\".",
37 Subject: remain.SourceRange().Ptr(),
38 })
39 } else {
40 diags = diags.Append(&hcl.Diagnostic{
41 Severity: hcl.DiagError,
42 Summary: "Invalid module instance address",
43 Detail: "The module instance address is followed by additional invalid content.",
44 Subject: remain.SourceRange().Ptr(),
45 })
46 }
47 }
48 return mi, diags
49}
50
51// ParseModuleInstanceStr is a helper wrapper around ParseModuleInstance
52// that takes a string and parses it with the HCL native syntax traversal parser
53// before interpreting it.
54//
55// This should be used only in specialized situations since it will cause the
56// created references to not have any meaningful source location information.
57// If a reference string is coming from a source that should be identified in
58// error messages then the caller should instead parse it directly using a
59// suitable function from the HCL API and pass the traversal itself to
60// ParseProviderConfigCompact.
61//
62// Error diagnostics are returned if either the parsing fails or the analysis
63// of the traversal fails. There is no way for the caller to distinguish the
64// two kinds of diagnostics programmatically. If error diagnostics are returned
65// then the returned address is invalid.
66func ParseModuleInstanceStr(str string) (ModuleInstance, tfdiags.Diagnostics) {
67 var diags tfdiags.Diagnostics
68
69 traversal, parseDiags := hclsyntax.ParseTraversalAbs([]byte(str), "", hcl.Pos{Line: 1, Column: 1})
70 diags = diags.Append(parseDiags)
71 if parseDiags.HasErrors() {
72 return nil, diags
73 }
74
75 addr, addrDiags := ParseModuleInstance(traversal)
76 diags = diags.Append(addrDiags)
77 return addr, diags
78}
79
80func parseModuleInstancePrefix(traversal hcl.Traversal) (ModuleInstance, hcl.Traversal, tfdiags.Diagnostics) {
81 remain := traversal
82 var mi ModuleInstance
83 var diags tfdiags.Diagnostics
84
85 for len(remain) > 0 {
86 var next string
87 switch tt := remain[0].(type) {
88 case hcl.TraverseRoot:
89 next = tt.Name
90 case hcl.TraverseAttr:
91 next = tt.Name
92 default:
93 diags = diags.Append(&hcl.Diagnostic{
94 Severity: hcl.DiagError,
95 Summary: "Invalid address operator",
96 Detail: "Module address prefix must be followed by dot and then a name.",
97 Subject: remain[0].SourceRange().Ptr(),
98 })
99 break
100 }
101
102 if next != "module" {
103 break
104 }
105
106 kwRange := remain[0].SourceRange()
107 remain = remain[1:]
108 // If we have the prefix "module" then we should be followed by an
109 // module call name, as an attribute, and then optionally an index step
110 // giving the instance key.
111 if len(remain) == 0 {
112 diags = diags.Append(&hcl.Diagnostic{
113 Severity: hcl.DiagError,
114 Summary: "Invalid address operator",
115 Detail: "Prefix \"module.\" must be followed by a module name.",
116 Subject: &kwRange,
117 })
118 break
119 }
120
121 var moduleName string
122 switch tt := remain[0].(type) {
123 case hcl.TraverseAttr:
124 moduleName = tt.Name
125 default:
126 diags = diags.Append(&hcl.Diagnostic{
127 Severity: hcl.DiagError,
128 Summary: "Invalid address operator",
129 Detail: "Prefix \"module.\" must be followed by a module name.",
130 Subject: remain[0].SourceRange().Ptr(),
131 })
132 break
133 }
134 remain = remain[1:]
135 step := ModuleInstanceStep{
136 Name: moduleName,
137 }
138
139 if len(remain) > 0 {
140 if idx, ok := remain[0].(hcl.TraverseIndex); ok {
141 remain = remain[1:]
142
143 switch idx.Key.Type() {
144 case cty.String:
145 step.InstanceKey = StringKey(idx.Key.AsString())
146 case cty.Number:
147 var idxInt int
148 err := gocty.FromCtyValue(idx.Key, &idxInt)
149 if err == nil {
150 step.InstanceKey = IntKey(idxInt)
151 } else {
152 diags = diags.Append(&hcl.Diagnostic{
153 Severity: hcl.DiagError,
154 Summary: "Invalid address operator",
155 Detail: fmt.Sprintf("Invalid module index: %s.", err),
156 Subject: idx.SourceRange().Ptr(),
157 })
158 }
159 default:
160 // Should never happen, because no other types are allowed in traversal indices.
161 diags = diags.Append(&hcl.Diagnostic{
162 Severity: hcl.DiagError,
163 Summary: "Invalid address operator",
164 Detail: "Invalid module key: must be either a string or an integer.",
165 Subject: idx.SourceRange().Ptr(),
166 })
167 }
168 }
169 }
170
171 mi = append(mi, step)
172 }
173
174 var retRemain hcl.Traversal
175 if len(remain) > 0 {
176 retRemain = make(hcl.Traversal, len(remain))
177 copy(retRemain, remain)
178 // The first element here might be either a TraverseRoot or a
179 // TraverseAttr, depending on whether we had a module address on the
180 // front. To make life easier for callers, we'll normalize to always
181 // start with a TraverseRoot.
182 if tt, ok := retRemain[0].(hcl.TraverseAttr); ok {
183 retRemain[0] = hcl.TraverseRoot{
184 Name: tt.Name,
185 SrcRange: tt.SrcRange,
186 }
187 }
188 }
189
190 return mi, retRemain, diags
191}
192
193// UnkeyedInstanceShim is a shim method for converting a Module address to the
194// equivalent ModuleInstance address that assumes that no modules have
195// keyed instances.
196//
197// This is a temporary allowance for the fact that Terraform does not presently
198// support "count" and "for_each" on modules, and thus graph building code that
199// derives graph nodes from configuration must just assume unkeyed modules
200// in order to construct the graph. At a later time when "count" and "for_each"
201// support is added for modules, all callers of this method will need to be
202// reworked to allow for keyed module instances.
203func (m Module) UnkeyedInstanceShim() ModuleInstance {
204 path := make(ModuleInstance, len(m))
205 for i, name := range m {
206 path[i] = ModuleInstanceStep{Name: name}
207 }
208 return path
209}
210
211// ModuleInstanceStep is a single traversal step through the dynamic module
212// tree. It is used only as part of ModuleInstance.
213type ModuleInstanceStep struct {
214 Name string
215 InstanceKey InstanceKey
216}
217
218// RootModuleInstance is the module instance address representing the root
219// module, which is also the zero value of ModuleInstance.
220var RootModuleInstance ModuleInstance
221
222// IsRoot returns true if the receiver is the address of the root module instance,
223// or false otherwise.
224func (m ModuleInstance) IsRoot() bool {
225 return len(m) == 0
226}
227
228// Child returns the address of a child module instance of the receiver,
229// identified by the given name and key.
230func (m ModuleInstance) Child(name string, key InstanceKey) ModuleInstance {
231 ret := make(ModuleInstance, 0, len(m)+1)
232 ret = append(ret, m...)
233 return append(ret, ModuleInstanceStep{
234 Name: name,
235 InstanceKey: key,
236 })
237}
238
239// Parent returns the address of the parent module instance of the receiver, or
240// the receiver itself if there is no parent (if it's the root module address).
241func (m ModuleInstance) Parent() ModuleInstance {
242 if len(m) == 0 {
243 return m
244 }
245 return m[:len(m)-1]
246}
247
248// String returns a string representation of the receiver, in the format used
249// within e.g. user-provided resource addresses.
250//
251// The address of the root module has the empty string as its representation.
252func (m ModuleInstance) String() string {
253 var buf bytes.Buffer
254 sep := ""
255 for _, step := range m {
256 buf.WriteString(sep)
257 buf.WriteString("module.")
258 buf.WriteString(step.Name)
259 if step.InstanceKey != NoKey {
260 buf.WriteString(step.InstanceKey.String())
261 }
262 sep = "."
263 }
264 return buf.String()
265}
266
267// Equal returns true if the receiver and the given other value
268// contains the exact same parts.
269func (m ModuleInstance) Equal(o ModuleInstance) bool {
270 return m.String() == o.String()
271}
272
273// Less returns true if the receiver should sort before the given other value
274// in a sorted list of addresses.
275func (m ModuleInstance) Less(o ModuleInstance) bool {
276 if len(m) != len(o) {
277 // Shorter path sorts first.
278 return len(m) < len(o)
279 }
280
281 for i := range m {
282 mS, oS := m[i], o[i]
283 switch {
284 case mS.Name != oS.Name:
285 return mS.Name < oS.Name
286 case mS.InstanceKey != oS.InstanceKey:
287 return InstanceKeyLess(mS.InstanceKey, oS.InstanceKey)
288 }
289 }
290
291 return false
292}
293
294// Ancestors returns a slice containing the receiver and all of its ancestor
295// module instances, all the way up to (and including) the root module.
296// The result is ordered by depth, with the root module always first.
297//
298// Since the result always includes the root module, a caller may choose to
299// ignore it by slicing the result with [1:].
300func (m ModuleInstance) Ancestors() []ModuleInstance {
301 ret := make([]ModuleInstance, 0, len(m)+1)
302 for i := 0; i <= len(m); i++ {
303 ret = append(ret, m[:i])
304 }
305 return ret
306}
307
308// IsAncestor returns true if the receiver is an ancestor of the given
309// other value.
310func (m ModuleInstance) IsAncestor(o ModuleInstance) bool {
311 // Longer or equal sized paths means the receiver cannot
312 // be an ancestor of the given module insatnce.
313 if len(m) >= len(o) {
314 return false
315 }
316
317 for i, ms := range m {
318 if ms.Name != o[i].Name {
319 return false
320 }
321 if ms.InstanceKey != NoKey && ms.InstanceKey != o[i].InstanceKey {
322 return false
323 }
324 }
325
326 return true
327}
328
329// Call returns the module call address that corresponds to the given module
330// instance, along with the address of the module instance that contains it.
331//
332// There is no call for the root module, so this method will panic if called
333// on the root module address.
334//
335// A single module call can produce potentially many module instances, so the
336// result discards any instance key that might be present on the last step
337// of the instance. To retain this, use CallInstance instead.
338//
339// In practice, this just turns the last element of the receiver into a
340// ModuleCall and then returns a slice of the receiever that excludes that
341// last part. This is just a convenience for situations where a call address
342// is required, such as when dealing with *Reference and Referencable values.
343func (m ModuleInstance) Call() (ModuleInstance, ModuleCall) {
344 if len(m) == 0 {
345 panic("cannot produce ModuleCall for root module")
346 }
347
348 inst, lastStep := m[:len(m)-1], m[len(m)-1]
349 return inst, ModuleCall{
350 Name: lastStep.Name,
351 }
352}
353
354// CallInstance returns the module call instance address that corresponds to
355// the given module instance, along with the address of the module instance
356// that contains it.
357//
358// There is no call for the root module, so this method will panic if called
359// on the root module address.
360//
361// In practice, this just turns the last element of the receiver into a
362// ModuleCallInstance and then returns a slice of the receiever that excludes
363// that last part. This is just a convenience for situations where a call\
364// address is required, such as when dealing with *Reference and Referencable
365// values.
366func (m ModuleInstance) CallInstance() (ModuleInstance, ModuleCallInstance) {
367 if len(m) == 0 {
368 panic("cannot produce ModuleCallInstance for root module")
369 }
370
371 inst, lastStep := m[:len(m)-1], m[len(m)-1]
372 return inst, ModuleCallInstance{
373 Call: ModuleCall{
374 Name: lastStep.Name,
375 },
376 Key: lastStep.InstanceKey,
377 }
378}
379
380// TargetContains implements Targetable by returning true if the given other
381// address either matches the receiver, is a sub-module-instance of the
382// receiver, or is a targetable absolute address within a module that
383// is contained within the reciever.
384func (m ModuleInstance) TargetContains(other Targetable) bool {
385 switch to := other.(type) {
386
387 case ModuleInstance:
388 if len(to) < len(m) {
389 // Can't be contained if the path is shorter
390 return false
391 }
392 // Other is contained if its steps match for the length of our own path.
393 for i, ourStep := range m {
394 otherStep := to[i]
395 if ourStep != otherStep {
396 return false
397 }
398 }
399 // If we fall out here then the prefixed matched, so it's contained.
400 return true
401
402 case AbsResource:
403 return m.TargetContains(to.Module)
404
405 case AbsResourceInstance:
406 return m.TargetContains(to.Module)
407
408 default:
409 return false
410 }
411}
412
413func (m ModuleInstance) targetableSigil() {
414 // ModuleInstance is targetable
415}
diff --git a/vendor/github.com/hashicorp/terraform/addrs/output_value.go b/vendor/github.com/hashicorp/terraform/addrs/output_value.go
new file mode 100644
index 0000000..bcd923a
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/addrs/output_value.go
@@ -0,0 +1,75 @@
1package addrs
2
3import (
4 "fmt"
5)
6
7// OutputValue is the address of an output value, in the context of the module
8// that is defining it.
9//
10// This is related to but separate from ModuleCallOutput, which represents
11// a module output from the perspective of its parent module. Since output
12// values cannot be represented from the module where they are defined,
13// OutputValue is not Referenceable, while ModuleCallOutput is.
14type OutputValue struct {
15 Name string
16}
17
18func (v OutputValue) String() string {
19 return "output." + v.Name
20}
21
22// Absolute converts the receiver into an absolute address within the given
23// module instance.
24func (v OutputValue) Absolute(m ModuleInstance) AbsOutputValue {
25 return AbsOutputValue{
26 Module: m,
27 OutputValue: v,
28 }
29}
30
31// AbsOutputValue is the absolute address of an output value within a module instance.
32//
33// This represents an output globally within the namespace of a particular
34// configuration. It is related to but separate from ModuleCallOutput, which
35// represents a module output from the perspective of its parent module.
36type AbsOutputValue struct {
37 Module ModuleInstance
38 OutputValue OutputValue
39}
40
41// OutputValue returns the absolute address of an output value of the given
42// name within the receiving module instance.
43func (m ModuleInstance) OutputValue(name string) AbsOutputValue {
44 return AbsOutputValue{
45 Module: m,
46 OutputValue: OutputValue{
47 Name: name,
48 },
49 }
50}
51
52func (v AbsOutputValue) String() string {
53 if v.Module.IsRoot() {
54 return v.OutputValue.String()
55 }
56 return fmt.Sprintf("%s.%s", v.Module.String(), v.OutputValue.String())
57}
58
59// ModuleCallOutput converts an AbsModuleOutput into a ModuleCallOutput,
60// returning also the module instance that the ModuleCallOutput is relative
61// to.
62//
63// The root module does not have a call, and so this method cannot be used
64// with outputs in the root module, and will panic in that case.
65func (v AbsOutputValue) ModuleCallOutput() (ModuleInstance, ModuleCallOutput) {
66 if v.Module.IsRoot() {
67 panic("ReferenceFromCall used with root module output")
68 }
69
70 caller, call := v.Module.CallInstance()
71 return caller, ModuleCallOutput{
72 Call: call,
73 Name: v.OutputValue.Name,
74 }
75}
diff --git a/vendor/github.com/hashicorp/terraform/addrs/parse_ref.go b/vendor/github.com/hashicorp/terraform/addrs/parse_ref.go
new file mode 100644
index 0000000..84fe8a0
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/addrs/parse_ref.go
@@ -0,0 +1,338 @@
1package addrs
2
3import (
4 "fmt"
5
6 "github.com/hashicorp/hcl2/hcl"
7 "github.com/hashicorp/hcl2/hcl/hclsyntax"
8 "github.com/hashicorp/terraform/tfdiags"
9)
10
11// Reference describes a reference to an address with source location
12// information.
13type Reference struct {
14 Subject Referenceable
15 SourceRange tfdiags.SourceRange
16 Remaining hcl.Traversal
17}
18
19// ParseRef attempts to extract a referencable address from the prefix of the
20// given traversal, which must be an absolute traversal or this function
21// will panic.
22//
23// If no error diagnostics are returned, the returned reference includes the
24// address that was extracted, the source range it was extracted from, and any
25// remaining relative traversal that was not consumed as part of the
26// reference.
27//
28// If error diagnostics are returned then the Reference value is invalid and
29// must not be used.
30func ParseRef(traversal hcl.Traversal) (*Reference, tfdiags.Diagnostics) {
31 ref, diags := parseRef(traversal)
32
33 // Normalize a little to make life easier for callers.
34 if ref != nil {
35 if len(ref.Remaining) == 0 {
36 ref.Remaining = nil
37 }
38 }
39
40 return ref, diags
41}
42
43// ParseRefStr is a helper wrapper around ParseRef that takes a string
44// and parses it with the HCL native syntax traversal parser before
45// interpreting it.
46//
47// This should be used only in specialized situations since it will cause the
48// created references to not have any meaningful source location information.
49// If a reference string is coming from a source that should be identified in
50// error messages then the caller should instead parse it directly using a
51// suitable function from the HCL API and pass the traversal itself to
52// ParseRef.
53//
54// Error diagnostics are returned if either the parsing fails or the analysis
55// of the traversal fails. There is no way for the caller to distinguish the
56// two kinds of diagnostics programmatically. If error diagnostics are returned
57// the returned reference may be nil or incomplete.
58func ParseRefStr(str string) (*Reference, tfdiags.Diagnostics) {
59 var diags tfdiags.Diagnostics
60
61 traversal, parseDiags := hclsyntax.ParseTraversalAbs([]byte(str), "", hcl.Pos{Line: 1, Column: 1})
62 diags = diags.Append(parseDiags)
63 if parseDiags.HasErrors() {
64 return nil, diags
65 }
66
67 ref, targetDiags := ParseRef(traversal)
68 diags = diags.Append(targetDiags)
69 return ref, diags
70}
71
72func parseRef(traversal hcl.Traversal) (*Reference, tfdiags.Diagnostics) {
73 var diags tfdiags.Diagnostics
74
75 root := traversal.RootName()
76 rootRange := traversal[0].SourceRange()
77
78 switch root {
79
80 case "count":
81 name, rng, remain, diags := parseSingleAttrRef(traversal)
82 return &Reference{
83 Subject: CountAttr{Name: name},
84 SourceRange: tfdiags.SourceRangeFromHCL(rng),
85 Remaining: remain,
86 }, diags
87
88 case "data":
89 if len(traversal) < 3 {
90 diags = diags.Append(&hcl.Diagnostic{
91 Severity: hcl.DiagError,
92 Summary: "Invalid reference",
93 Detail: `The "data" object must be followed by two attribute names: the data source type and the resource name.`,
94 Subject: traversal.SourceRange().Ptr(),
95 })
96 return nil, diags
97 }
98 remain := traversal[1:] // trim off "data" so we can use our shared resource reference parser
99 return parseResourceRef(DataResourceMode, rootRange, remain)
100
101 case "local":
102 name, rng, remain, diags := parseSingleAttrRef(traversal)
103 return &Reference{
104 Subject: LocalValue{Name: name},
105 SourceRange: tfdiags.SourceRangeFromHCL(rng),
106 Remaining: remain,
107 }, diags
108
109 case "module":
110 callName, callRange, remain, diags := parseSingleAttrRef(traversal)
111 if diags.HasErrors() {
112 return nil, diags
113 }
114
115 // A traversal starting with "module" can either be a reference to
116 // an entire module instance or to a single output from a module
117 // instance, depending on what we find after this introducer.
118
119 callInstance := ModuleCallInstance{
120 Call: ModuleCall{
121 Name: callName,
122 },
123 Key: NoKey,
124 }
125
126 if len(remain) == 0 {
127 // Reference to an entire module instance. Might alternatively
128 // be a reference to a collection of instances of a particular
129 // module, but the caller will need to deal with that ambiguity
130 // since we don't have enough context here.
131 return &Reference{
132 Subject: callInstance,
133 SourceRange: tfdiags.SourceRangeFromHCL(callRange),
134 Remaining: remain,
135 }, diags
136 }
137
138 if idxTrav, ok := remain[0].(hcl.TraverseIndex); ok {
139 var err error
140 callInstance.Key, err = ParseInstanceKey(idxTrav.Key)
141 if err != nil {
142 diags = diags.Append(&hcl.Diagnostic{
143 Severity: hcl.DiagError,
144 Summary: "Invalid index key",
145 Detail: fmt.Sprintf("Invalid index for module instance: %s.", err),
146 Subject: &idxTrav.SrcRange,
147 })
148 return nil, diags
149 }
150 remain = remain[1:]
151
152 if len(remain) == 0 {
153 // Also a reference to an entire module instance, but we have a key
154 // now.
155 return &Reference{
156 Subject: callInstance,
157 SourceRange: tfdiags.SourceRangeFromHCL(hcl.RangeBetween(callRange, idxTrav.SrcRange)),
158 Remaining: remain,
159 }, diags
160 }
161 }
162
163 if attrTrav, ok := remain[0].(hcl.TraverseAttr); ok {
164 remain = remain[1:]
165 return &Reference{
166 Subject: ModuleCallOutput{
167 Name: attrTrav.Name,
168 Call: callInstance,
169 },
170 SourceRange: tfdiags.SourceRangeFromHCL(hcl.RangeBetween(callRange, attrTrav.SrcRange)),
171 Remaining: remain,
172 }, diags
173 }
174
175 diags = diags.Append(&hcl.Diagnostic{
176 Severity: hcl.DiagError,
177 Summary: "Invalid reference",
178 Detail: "Module instance objects do not support this operation.",
179 Subject: remain[0].SourceRange().Ptr(),
180 })
181 return nil, diags
182
183 case "path":
184 name, rng, remain, diags := parseSingleAttrRef(traversal)
185 return &Reference{
186 Subject: PathAttr{Name: name},
187 SourceRange: tfdiags.SourceRangeFromHCL(rng),
188 Remaining: remain,
189 }, diags
190
191 case "self":
192 return &Reference{
193 Subject: Self,
194 SourceRange: tfdiags.SourceRangeFromHCL(rootRange),
195 Remaining: traversal[1:],
196 }, diags
197
198 case "terraform":
199 name, rng, remain, diags := parseSingleAttrRef(traversal)
200 return &Reference{
201 Subject: TerraformAttr{Name: name},
202 SourceRange: tfdiags.SourceRangeFromHCL(rng),
203 Remaining: remain,
204 }, diags
205
206 case "var":
207 name, rng, remain, diags := parseSingleAttrRef(traversal)
208 return &Reference{
209 Subject: InputVariable{Name: name},
210 SourceRange: tfdiags.SourceRangeFromHCL(rng),
211 Remaining: remain,
212 }, diags
213
214 default:
215 return parseResourceRef(ManagedResourceMode, rootRange, traversal)
216 }
217}
218
219func parseResourceRef(mode ResourceMode, startRange hcl.Range, traversal hcl.Traversal) (*Reference, tfdiags.Diagnostics) {
220 var diags tfdiags.Diagnostics
221
222 if len(traversal) < 2 {
223 diags = diags.Append(&hcl.Diagnostic{
224 Severity: hcl.DiagError,
225 Summary: "Invalid reference",
226 Detail: `A reference to a resource type must be followed by at least one attribute access, specifying the resource name.`,
227 Subject: hcl.RangeBetween(traversal[0].SourceRange(), traversal[len(traversal)-1].SourceRange()).Ptr(),
228 })
229 return nil, diags
230 }
231
232 var typeName, name string
233 switch tt := traversal[0].(type) { // Could be either root or attr, depending on our resource mode
234 case hcl.TraverseRoot:
235 typeName = tt.Name
236 case hcl.TraverseAttr:
237 typeName = tt.Name
238 default:
239 // If it isn't a TraverseRoot then it must be a "data" reference.
240 diags = diags.Append(&hcl.Diagnostic{
241 Severity: hcl.DiagError,
242 Summary: "Invalid reference",
243 Detail: `The "data" object does not support this operation.`,
244 Subject: traversal[0].SourceRange().Ptr(),
245 })
246 return nil, diags
247 }
248
249 attrTrav, ok := traversal[1].(hcl.TraverseAttr)
250 if !ok {
251 var what string
252 switch mode {
253 case DataResourceMode:
254 what = "data source"
255 default:
256 what = "resource type"
257 }
258 diags = diags.Append(&hcl.Diagnostic{
259 Severity: hcl.DiagError,
260 Summary: "Invalid reference",
261 Detail: fmt.Sprintf(`A reference to a %s must be followed by at least one attribute access, specifying the resource name.`, what),
262 Subject: traversal[1].SourceRange().Ptr(),
263 })
264 return nil, diags
265 }
266 name = attrTrav.Name
267 rng := hcl.RangeBetween(startRange, attrTrav.SrcRange)
268 remain := traversal[2:]
269
270 resourceAddr := Resource{
271 Mode: mode,
272 Type: typeName,
273 Name: name,
274 }
275 resourceInstAddr := ResourceInstance{
276 Resource: resourceAddr,
277 Key: NoKey,
278 }
279
280 if len(remain) == 0 {
281 // This might actually be a reference to the collection of all instances
282 // of the resource, but we don't have enough context here to decide
283 // so we'll let the caller resolve that ambiguity.
284 return &Reference{
285 Subject: resourceInstAddr,
286 SourceRange: tfdiags.SourceRangeFromHCL(rng),
287 }, diags
288 }
289
290 if idxTrav, ok := remain[0].(hcl.TraverseIndex); ok {
291 var err error
292 resourceInstAddr.Key, err = ParseInstanceKey(idxTrav.Key)
293 if err != nil {
294 diags = diags.Append(&hcl.Diagnostic{
295 Severity: hcl.DiagError,
296 Summary: "Invalid index key",
297 Detail: fmt.Sprintf("Invalid index for resource instance: %s.", err),
298 Subject: &idxTrav.SrcRange,
299 })
300 return nil, diags
301 }
302 remain = remain[1:]
303 rng = hcl.RangeBetween(rng, idxTrav.SrcRange)
304 }
305
306 return &Reference{
307 Subject: resourceInstAddr,
308 SourceRange: tfdiags.SourceRangeFromHCL(rng),
309 Remaining: remain,
310 }, diags
311}
312
313func parseSingleAttrRef(traversal hcl.Traversal) (string, hcl.Range, hcl.Traversal, tfdiags.Diagnostics) {
314 var diags tfdiags.Diagnostics
315
316 root := traversal.RootName()
317 rootRange := traversal[0].SourceRange()
318
319 if len(traversal) < 2 {
320 diags = diags.Append(&hcl.Diagnostic{
321 Severity: hcl.DiagError,
322 Summary: "Invalid reference",
323 Detail: fmt.Sprintf("The %q object cannot be accessed directly. Instead, access one of its attributes.", root),
324 Subject: &rootRange,
325 })
326 return "", hcl.Range{}, nil, diags
327 }
328 if attrTrav, ok := traversal[1].(hcl.TraverseAttr); ok {
329 return attrTrav.Name, hcl.RangeBetween(rootRange, attrTrav.SrcRange), traversal[2:], diags
330 }
331 diags = diags.Append(&hcl.Diagnostic{
332 Severity: hcl.DiagError,
333 Summary: "Invalid reference",
334 Detail: fmt.Sprintf("The %q object does not support this operation.", root),
335 Subject: traversal[1].SourceRange().Ptr(),
336 })
337 return "", hcl.Range{}, nil, diags
338}
diff --git a/vendor/github.com/hashicorp/terraform/addrs/parse_target.go b/vendor/github.com/hashicorp/terraform/addrs/parse_target.go
new file mode 100644
index 0000000..057443a
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/addrs/parse_target.go
@@ -0,0 +1,318 @@
1package addrs
2
3import (
4 "fmt"
5
6 "github.com/hashicorp/hcl2/hcl/hclsyntax"
7
8 "github.com/hashicorp/hcl2/hcl"
9 "github.com/hashicorp/terraform/tfdiags"
10)
11
12// Target describes a targeted address with source location information.
13type Target struct {
14 Subject Targetable
15 SourceRange tfdiags.SourceRange
16}
17
18// ParseTarget attempts to interpret the given traversal as a targetable
19// address. The given traversal must be absolute, or this function will
20// panic.
21//
22// If no error diagnostics are returned, the returned target includes the
23// address that was extracted and the source range it was extracted from.
24//
25// If error diagnostics are returned then the Target value is invalid and
26// must not be used.
27func ParseTarget(traversal hcl.Traversal) (*Target, tfdiags.Diagnostics) {
28 path, remain, diags := parseModuleInstancePrefix(traversal)
29 if diags.HasErrors() {
30 return nil, diags
31 }
32
33 rng := tfdiags.SourceRangeFromHCL(traversal.SourceRange())
34
35 if len(remain) == 0 {
36 return &Target{
37 Subject: path,
38 SourceRange: rng,
39 }, diags
40 }
41
42 mode := ManagedResourceMode
43 if remain.RootName() == "data" {
44 mode = DataResourceMode
45 remain = remain[1:]
46 }
47
48 if len(remain) < 2 {
49 diags = diags.Append(&hcl.Diagnostic{
50 Severity: hcl.DiagError,
51 Summary: "Invalid address",
52 Detail: "Resource specification must include a resource type and name.",
53 Subject: remain.SourceRange().Ptr(),
54 })
55 return nil, diags
56 }
57
58 var typeName, name string
59 switch tt := remain[0].(type) {
60 case hcl.TraverseRoot:
61 typeName = tt.Name
62 case hcl.TraverseAttr:
63 typeName = tt.Name
64 default:
65 switch mode {
66 case ManagedResourceMode:
67 diags = diags.Append(&hcl.Diagnostic{
68 Severity: hcl.DiagError,
69 Summary: "Invalid address",
70 Detail: "A resource type name is required.",
71 Subject: remain[0].SourceRange().Ptr(),
72 })
73 case DataResourceMode:
74 diags = diags.Append(&hcl.Diagnostic{
75 Severity: hcl.DiagError,
76 Summary: "Invalid address",
77 Detail: "A data source name is required.",
78 Subject: remain[0].SourceRange().Ptr(),
79 })
80 default:
81 panic("unknown mode")
82 }
83 return nil, diags
84 }
85
86 switch tt := remain[1].(type) {
87 case hcl.TraverseAttr:
88 name = tt.Name
89 default:
90 diags = diags.Append(&hcl.Diagnostic{
91 Severity: hcl.DiagError,
92 Summary: "Invalid address",
93 Detail: "A resource name is required.",
94 Subject: remain[1].SourceRange().Ptr(),
95 })
96 return nil, diags
97 }
98
99 var subject Targetable
100 remain = remain[2:]
101 switch len(remain) {
102 case 0:
103 subject = path.Resource(mode, typeName, name)
104 case 1:
105 if tt, ok := remain[0].(hcl.TraverseIndex); ok {
106 key, err := ParseInstanceKey(tt.Key)
107 if err != nil {
108 diags = diags.Append(&hcl.Diagnostic{
109 Severity: hcl.DiagError,
110 Summary: "Invalid address",
111 Detail: fmt.Sprintf("Invalid resource instance key: %s.", err),
112 Subject: remain[0].SourceRange().Ptr(),
113 })
114 return nil, diags
115 }
116
117 subject = path.ResourceInstance(mode, typeName, name, key)
118 } else {
119 diags = diags.Append(&hcl.Diagnostic{
120 Severity: hcl.DiagError,
121 Summary: "Invalid address",
122 Detail: "Resource instance key must be given in square brackets.",
123 Subject: remain[0].SourceRange().Ptr(),
124 })
125 return nil, diags
126 }
127 default:
128 diags = diags.Append(&hcl.Diagnostic{
129 Severity: hcl.DiagError,
130 Summary: "Invalid address",
131 Detail: "Unexpected extra operators after address.",
132 Subject: remain[1].SourceRange().Ptr(),
133 })
134 return nil, diags
135 }
136
137 return &Target{
138 Subject: subject,
139 SourceRange: rng,
140 }, diags
141}
142
143// ParseTargetStr is a helper wrapper around ParseTarget that takes a string
144// and parses it with the HCL native syntax traversal parser before
145// interpreting it.
146//
147// This should be used only in specialized situations since it will cause the
148// created references to not have any meaningful source location information.
149// If a target string is coming from a source that should be identified in
150// error messages then the caller should instead parse it directly using a
151// suitable function from the HCL API and pass the traversal itself to
152// ParseTarget.
153//
154// Error diagnostics are returned if either the parsing fails or the analysis
155// of the traversal fails. There is no way for the caller to distinguish the
156// two kinds of diagnostics programmatically. If error diagnostics are returned
157// the returned target may be nil or incomplete.
158func ParseTargetStr(str string) (*Target, tfdiags.Diagnostics) {
159 var diags tfdiags.Diagnostics
160
161 traversal, parseDiags := hclsyntax.ParseTraversalAbs([]byte(str), "", hcl.Pos{Line: 1, Column: 1})
162 diags = diags.Append(parseDiags)
163 if parseDiags.HasErrors() {
164 return nil, diags
165 }
166
167 target, targetDiags := ParseTarget(traversal)
168 diags = diags.Append(targetDiags)
169 return target, diags
170}
171
172// ParseAbsResource attempts to interpret the given traversal as an absolute
173// resource address, using the same syntax as expected by ParseTarget.
174//
175// If no error diagnostics are returned, the returned target includes the
176// address that was extracted and the source range it was extracted from.
177//
178// If error diagnostics are returned then the AbsResource value is invalid and
179// must not be used.
180func ParseAbsResource(traversal hcl.Traversal) (AbsResource, tfdiags.Diagnostics) {
181 addr, diags := ParseTarget(traversal)
182 if diags.HasErrors() {
183 return AbsResource{}, diags
184 }
185
186 switch tt := addr.Subject.(type) {
187
188 case AbsResource:
189 return tt, diags
190
191 case AbsResourceInstance: // Catch likely user error with specialized message
192 // Assume that the last element of the traversal must be the index,
193 // since that's required for a valid resource instance address.
194 indexStep := traversal[len(traversal)-1]
195 diags = diags.Append(&hcl.Diagnostic{
196 Severity: hcl.DiagError,
197 Summary: "Invalid address",
198 Detail: "A resource address is required. This instance key identifies a specific resource instance, which is not expected here.",
199 Subject: indexStep.SourceRange().Ptr(),
200 })
201 return AbsResource{}, diags
202
203 case ModuleInstance: // Catch likely user error with specialized message
204 diags = diags.Append(&hcl.Diagnostic{
205 Severity: hcl.DiagError,
206 Summary: "Invalid address",
207 Detail: "A resource address is required here. The module path must be followed by a resource specification.",
208 Subject: traversal.SourceRange().Ptr(),
209 })
210 return AbsResource{}, diags
211
212 default: // Generic message for other address types
213 diags = diags.Append(&hcl.Diagnostic{
214 Severity: hcl.DiagError,
215 Summary: "Invalid address",
216 Detail: "A resource address is required here.",
217 Subject: traversal.SourceRange().Ptr(),
218 })
219 return AbsResource{}, diags
220
221 }
222}
223
224// ParseAbsResourceStr is a helper wrapper around ParseAbsResource that takes a
225// string and parses it with the HCL native syntax traversal parser before
226// interpreting it.
227//
228// Error diagnostics are returned if either the parsing fails or the analysis
229// of the traversal fails. There is no way for the caller to distinguish the
230// two kinds of diagnostics programmatically. If error diagnostics are returned
231// the returned address may be incomplete.
232//
233// Since this function has no context about the source of the given string,
234// any returned diagnostics will not have meaningful source location
235// information.
236func ParseAbsResourceStr(str string) (AbsResource, tfdiags.Diagnostics) {
237 var diags tfdiags.Diagnostics
238
239 traversal, parseDiags := hclsyntax.ParseTraversalAbs([]byte(str), "", hcl.Pos{Line: 1, Column: 1})
240 diags = diags.Append(parseDiags)
241 if parseDiags.HasErrors() {
242 return AbsResource{}, diags
243 }
244
245 addr, addrDiags := ParseAbsResource(traversal)
246 diags = diags.Append(addrDiags)
247 return addr, diags
248}
249
250// ParseAbsResourceInstance attempts to interpret the given traversal as an
251// absolute resource instance address, using the same syntax as expected by
252// ParseTarget.
253//
254// If no error diagnostics are returned, the returned target includes the
255// address that was extracted and the source range it was extracted from.
256//
257// If error diagnostics are returned then the AbsResource value is invalid and
258// must not be used.
259func ParseAbsResourceInstance(traversal hcl.Traversal) (AbsResourceInstance, tfdiags.Diagnostics) {
260 addr, diags := ParseTarget(traversal)
261 if diags.HasErrors() {
262 return AbsResourceInstance{}, diags
263 }
264
265 switch tt := addr.Subject.(type) {
266
267 case AbsResource:
268 return tt.Instance(NoKey), diags
269
270 case AbsResourceInstance:
271 return tt, diags
272
273 case ModuleInstance: // Catch likely user error with specialized message
274 diags = diags.Append(&hcl.Diagnostic{
275 Severity: hcl.DiagError,
276 Summary: "Invalid address",
277 Detail: "A resource instance address is required here. The module path must be followed by a resource instance specification.",
278 Subject: traversal.SourceRange().Ptr(),
279 })
280 return AbsResourceInstance{}, diags
281
282 default: // Generic message for other address types
283 diags = diags.Append(&hcl.Diagnostic{
284 Severity: hcl.DiagError,
285 Summary: "Invalid address",
286 Detail: "A resource address is required here.",
287 Subject: traversal.SourceRange().Ptr(),
288 })
289 return AbsResourceInstance{}, diags
290
291 }
292}
293
294// ParseAbsResourceInstanceStr is a helper wrapper around
295// ParseAbsResourceInstance that takes a string and parses it with the HCL
296// native syntax traversal parser before interpreting it.
297//
298// Error diagnostics are returned if either the parsing fails or the analysis
299// of the traversal fails. There is no way for the caller to distinguish the
300// two kinds of diagnostics programmatically. If error diagnostics are returned
301// the returned address may be incomplete.
302//
303// Since this function has no context about the source of the given string,
304// any returned diagnostics will not have meaningful source location
305// information.
306func ParseAbsResourceInstanceStr(str string) (AbsResourceInstance, tfdiags.Diagnostics) {
307 var diags tfdiags.Diagnostics
308
309 traversal, parseDiags := hclsyntax.ParseTraversalAbs([]byte(str), "", hcl.Pos{Line: 1, Column: 1})
310 diags = diags.Append(parseDiags)
311 if parseDiags.HasErrors() {
312 return AbsResourceInstance{}, diags
313 }
314
315 addr, addrDiags := ParseAbsResourceInstance(traversal)
316 diags = diags.Append(addrDiags)
317 return addr, diags
318}
diff --git a/vendor/github.com/hashicorp/terraform/addrs/path_attr.go b/vendor/github.com/hashicorp/terraform/addrs/path_attr.go
new file mode 100644
index 0000000..cfc13f4
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/addrs/path_attr.go
@@ -0,0 +1,12 @@
1package addrs
2
3// PathAttr is the address of an attribute of the "path" object in
4// the interpolation scope, like "path.module".
5type PathAttr struct {
6 referenceable
7 Name string
8}
9
10func (pa PathAttr) String() string {
11 return "path." + pa.Name
12}
diff --git a/vendor/github.com/hashicorp/terraform/addrs/provider_config.go b/vendor/github.com/hashicorp/terraform/addrs/provider_config.go
new file mode 100644
index 0000000..340dd19
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/addrs/provider_config.go
@@ -0,0 +1,297 @@
1package addrs
2
3import (
4 "fmt"
5
6 "github.com/hashicorp/terraform/tfdiags"
7
8 "github.com/hashicorp/hcl2/hcl"
9 "github.com/hashicorp/hcl2/hcl/hclsyntax"
10)
11
12// ProviderConfig is the address of a provider configuration.
13type ProviderConfig struct {
14 Type string
15
16 // If not empty, Alias identifies which non-default (aliased) provider
17 // configuration this address refers to.
18 Alias string
19}
20
21// NewDefaultProviderConfig returns the address of the default (un-aliased)
22// configuration for the provider with the given type name.
23func NewDefaultProviderConfig(typeName string) ProviderConfig {
24 return ProviderConfig{
25 Type: typeName,
26 }
27}
28
29// ParseProviderConfigCompact parses the given absolute traversal as a relative
30// provider address in compact form. The following are examples of traversals
31// that can be successfully parsed as compact relative provider configuration
32// addresses:
33//
34// aws
35// aws.foo
36//
37// This function will panic if given a relative traversal.
38//
39// If the returned diagnostics contains errors then the result value is invalid
40// and must not be used.
41func ParseProviderConfigCompact(traversal hcl.Traversal) (ProviderConfig, tfdiags.Diagnostics) {
42 var diags tfdiags.Diagnostics
43 ret := ProviderConfig{
44 Type: traversal.RootName(),
45 }
46
47 if len(traversal) < 2 {
48 // Just a type name, then.
49 return ret, diags
50 }
51
52 aliasStep := traversal[1]
53 switch ts := aliasStep.(type) {
54 case hcl.TraverseAttr:
55 ret.Alias = ts.Name
56 return ret, diags
57 default:
58 diags = diags.Append(&hcl.Diagnostic{
59 Severity: hcl.DiagError,
60 Summary: "Invalid provider configuration address",
61 Detail: "The provider type name must either stand alone or be followed by an alias name separated with a dot.",
62 Subject: aliasStep.SourceRange().Ptr(),
63 })
64 }
65
66 if len(traversal) > 2 {
67 diags = diags.Append(&hcl.Diagnostic{
68 Severity: hcl.DiagError,
69 Summary: "Invalid provider configuration address",
70 Detail: "Extraneous extra operators after provider configuration address.",
71 Subject: traversal[2:].SourceRange().Ptr(),
72 })
73 }
74
75 return ret, diags
76}
77
78// ParseProviderConfigCompactStr is a helper wrapper around ParseProviderConfigCompact
79// that takes a string and parses it with the HCL native syntax traversal parser
80// before interpreting it.
81//
82// This should be used only in specialized situations since it will cause the
83// created references to not have any meaningful source location information.
84// If a reference string is coming from a source that should be identified in
85// error messages then the caller should instead parse it directly using a
86// suitable function from the HCL API and pass the traversal itself to
87// ParseProviderConfigCompact.
88//
89// Error diagnostics are returned if either the parsing fails or the analysis
90// of the traversal fails. There is no way for the caller to distinguish the
91// two kinds of diagnostics programmatically. If error diagnostics are returned
92// then the returned address is invalid.
93func ParseProviderConfigCompactStr(str string) (ProviderConfig, tfdiags.Diagnostics) {
94 var diags tfdiags.Diagnostics
95
96 traversal, parseDiags := hclsyntax.ParseTraversalAbs([]byte(str), "", hcl.Pos{Line: 1, Column: 1})
97 diags = diags.Append(parseDiags)
98 if parseDiags.HasErrors() {
99 return ProviderConfig{}, diags
100 }
101
102 addr, addrDiags := ParseProviderConfigCompact(traversal)
103 diags = diags.Append(addrDiags)
104 return addr, diags
105}
106
107// Absolute returns an AbsProviderConfig from the receiver and the given module
108// instance address.
109func (pc ProviderConfig) Absolute(module ModuleInstance) AbsProviderConfig {
110 return AbsProviderConfig{
111 Module: module,
112 ProviderConfig: pc,
113 }
114}
115
116func (pc ProviderConfig) String() string {
117 if pc.Type == "" {
118 // Should never happen; always indicates a bug
119 return "provider.<invalid>"
120 }
121
122 if pc.Alias != "" {
123 return fmt.Sprintf("provider.%s.%s", pc.Type, pc.Alias)
124 }
125
126 return "provider." + pc.Type
127}
128
129// StringCompact is an alternative to String that returns the form that can
130// be parsed by ParseProviderConfigCompact, without the "provider." prefix.
131func (pc ProviderConfig) StringCompact() string {
132 if pc.Alias != "" {
133 return fmt.Sprintf("%s.%s", pc.Type, pc.Alias)
134 }
135 return pc.Type
136}
137
138// AbsProviderConfig is the absolute address of a provider configuration
139// within a particular module instance.
140type AbsProviderConfig struct {
141 Module ModuleInstance
142 ProviderConfig ProviderConfig
143}
144
145// ParseAbsProviderConfig parses the given traversal as an absolute provider
146// address. The following are examples of traversals that can be successfully
147// parsed as absolute provider configuration addresses:
148//
149// provider.aws
150// provider.aws.foo
151// module.bar.provider.aws
152// module.bar.module.baz.provider.aws.foo
153// module.foo[1].provider.aws.foo
154//
155// This type of address is used, for example, to record the relationships
156// between resources and provider configurations in the state structure.
157// This type of address is not generally used in the UI, except in error
158// messages that refer to provider configurations.
159func ParseAbsProviderConfig(traversal hcl.Traversal) (AbsProviderConfig, tfdiags.Diagnostics) {
160 modInst, remain, diags := parseModuleInstancePrefix(traversal)
161 ret := AbsProviderConfig{
162 Module: modInst,
163 }
164 if len(remain) < 2 || remain.RootName() != "provider" {
165 diags = diags.Append(&hcl.Diagnostic{
166 Severity: hcl.DiagError,
167 Summary: "Invalid provider configuration address",
168 Detail: "Provider address must begin with \"provider.\", followed by a provider type name.",
169 Subject: remain.SourceRange().Ptr(),
170 })
171 return ret, diags
172 }
173 if len(remain) > 3 {
174 diags = diags.Append(&hcl.Diagnostic{
175 Severity: hcl.DiagError,
176 Summary: "Invalid provider configuration address",
177 Detail: "Extraneous operators after provider configuration alias.",
178 Subject: hcl.Traversal(remain[3:]).SourceRange().Ptr(),
179 })
180 return ret, diags
181 }
182
183 if tt, ok := remain[1].(hcl.TraverseAttr); ok {
184 ret.ProviderConfig.Type = tt.Name
185 } else {
186 diags = diags.Append(&hcl.Diagnostic{
187 Severity: hcl.DiagError,
188 Summary: "Invalid provider configuration address",
189 Detail: "The prefix \"provider.\" must be followed by a provider type name.",
190 Subject: remain[1].SourceRange().Ptr(),
191 })
192 return ret, diags
193 }
194
195 if len(remain) == 3 {
196 if tt, ok := remain[2].(hcl.TraverseAttr); ok {
197 ret.ProviderConfig.Alias = tt.Name
198 } else {
199 diags = diags.Append(&hcl.Diagnostic{
200 Severity: hcl.DiagError,
201 Summary: "Invalid provider configuration address",
202 Detail: "Provider type name must be followed by a configuration alias name.",
203 Subject: remain[2].SourceRange().Ptr(),
204 })
205 return ret, diags
206 }
207 }
208
209 return ret, diags
210}
211
212// ParseAbsProviderConfigStr is a helper wrapper around ParseAbsProviderConfig
213// that takes a string and parses it with the HCL native syntax traversal parser
214// before interpreting it.
215//
216// This should be used only in specialized situations since it will cause the
217// created references to not have any meaningful source location information.
218// If a reference string is coming from a source that should be identified in
219// error messages then the caller should instead parse it directly using a
220// suitable function from the HCL API and pass the traversal itself to
221// ParseAbsProviderConfig.
222//
223// Error diagnostics are returned if either the parsing fails or the analysis
224// of the traversal fails. There is no way for the caller to distinguish the
225// two kinds of diagnostics programmatically. If error diagnostics are returned
226// the returned address is invalid.
227func ParseAbsProviderConfigStr(str string) (AbsProviderConfig, tfdiags.Diagnostics) {
228 var diags tfdiags.Diagnostics
229
230 traversal, parseDiags := hclsyntax.ParseTraversalAbs([]byte(str), "", hcl.Pos{Line: 1, Column: 1})
231 diags = diags.Append(parseDiags)
232 if parseDiags.HasErrors() {
233 return AbsProviderConfig{}, diags
234 }
235
236 addr, addrDiags := ParseAbsProviderConfig(traversal)
237 diags = diags.Append(addrDiags)
238 return addr, diags
239}
240
241// ProviderConfigDefault returns the address of the default provider config
242// of the given type inside the recieving module instance.
243func (m ModuleInstance) ProviderConfigDefault(name string) AbsProviderConfig {
244 return AbsProviderConfig{
245 Module: m,
246 ProviderConfig: ProviderConfig{
247 Type: name,
248 },
249 }
250}
251
252// ProviderConfigAliased returns the address of an aliased provider config
253// of with given type and alias inside the recieving module instance.
254func (m ModuleInstance) ProviderConfigAliased(name, alias string) AbsProviderConfig {
255 return AbsProviderConfig{
256 Module: m,
257 ProviderConfig: ProviderConfig{
258 Type: name,
259 Alias: alias,
260 },
261 }
262}
263
264// Inherited returns an address that the receiving configuration address might
265// inherit from in a parent module. The second bool return value indicates if
266// such inheritance is possible, and thus whether the returned address is valid.
267//
268// Inheritance is possible only for default (un-aliased) providers in modules
269// other than the root module. Even if a valid address is returned, inheritence
270// may not be performed for other reasons, such as if the calling module
271// provided explicit provider configurations within the call for this module.
272// The ProviderTransformer graph transform in the main terraform module has
273// the authoritative logic for provider inheritance, and this method is here
274// mainly just for its benefit.
275func (pc AbsProviderConfig) Inherited() (AbsProviderConfig, bool) {
276 // Can't inherit if we're already in the root.
277 if len(pc.Module) == 0 {
278 return AbsProviderConfig{}, false
279 }
280
281 // Can't inherit if we have an alias.
282 if pc.ProviderConfig.Alias != "" {
283 return AbsProviderConfig{}, false
284 }
285
286 // Otherwise, we might inherit from a configuration with the same
287 // provider name in the parent module instance.
288 parentMod := pc.Module.Parent()
289 return pc.ProviderConfig.Absolute(parentMod), true
290}
291
292func (pc AbsProviderConfig) String() string {
293 if len(pc.Module) == 0 {
294 return pc.ProviderConfig.String()
295 }
296 return fmt.Sprintf("%s.%s", pc.Module.String(), pc.ProviderConfig.String())
297}
diff --git a/vendor/github.com/hashicorp/terraform/addrs/referenceable.go b/vendor/github.com/hashicorp/terraform/addrs/referenceable.go
new file mode 100644
index 0000000..211083a
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/addrs/referenceable.go
@@ -0,0 +1,20 @@
1package addrs
2
3// Referenceable is an interface implemented by all address types that can
4// appear as references in configuration language expressions.
5type Referenceable interface {
6 // All implementations of this interface must be covered by the type switch
7 // in lang.Scope.buildEvalContext.
8 referenceableSigil()
9
10 // String produces a string representation of the address that could be
11 // parsed as a HCL traversal and passed to ParseRef to produce an identical
12 // result.
13 String() string
14}
15
16type referenceable struct {
17}
18
19func (r referenceable) referenceableSigil() {
20}
diff --git a/vendor/github.com/hashicorp/terraform/addrs/resource.go b/vendor/github.com/hashicorp/terraform/addrs/resource.go
new file mode 100644
index 0000000..2866770
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/addrs/resource.go
@@ -0,0 +1,270 @@
1package addrs
2
3import (
4 "fmt"
5 "strings"
6)
7
8// Resource is an address for a resource block within configuration, which
9// contains potentially-multiple resource instances if that configuration
10// block uses "count" or "for_each".
11type Resource struct {
12 referenceable
13 Mode ResourceMode
14 Type string
15 Name string
16}
17
18func (r Resource) String() string {
19 switch r.Mode {
20 case ManagedResourceMode:
21 return fmt.Sprintf("%s.%s", r.Type, r.Name)
22 case DataResourceMode:
23 return fmt.Sprintf("data.%s.%s", r.Type, r.Name)
24 default:
25 // Should never happen, but we'll return a string here rather than
26 // crashing just in case it does.
27 return fmt.Sprintf("<invalid>.%s.%s", r.Type, r.Name)
28 }
29}
30
31func (r Resource) Equal(o Resource) bool {
32 return r.String() == o.String()
33}
34
35// Instance produces the address for a specific instance of the receiver
36// that is idenfied by the given key.
37func (r Resource) Instance(key InstanceKey) ResourceInstance {
38 return ResourceInstance{
39 Resource: r,
40 Key: key,
41 }
42}
43
44// Absolute returns an AbsResource from the receiver and the given module
45// instance address.
46func (r Resource) Absolute(module ModuleInstance) AbsResource {
47 return AbsResource{
48 Module: module,
49 Resource: r,
50 }
51}
52
53// DefaultProviderConfig returns the address of the provider configuration
54// that should be used for the resource identified by the reciever if it
55// does not have a provider configuration address explicitly set in
56// configuration.
57//
58// This method is not able to verify that such a configuration exists, nor
59// represent the behavior of automatically inheriting certain provider
60// configurations from parent modules. It just does a static analysis of the
61// receiving address and returns an address to start from, relative to the
62// same module that contains the resource.
63func (r Resource) DefaultProviderConfig() ProviderConfig {
64 typeName := r.Type
65 if under := strings.Index(typeName, "_"); under != -1 {
66 typeName = typeName[:under]
67 }
68 return ProviderConfig{
69 Type: typeName,
70 }
71}
72
73// ResourceInstance is an address for a specific instance of a resource.
74// When a resource is defined in configuration with "count" or "for_each" it
75// produces zero or more instances, which can be addressed using this type.
76type ResourceInstance struct {
77 referenceable
78 Resource Resource
79 Key InstanceKey
80}
81
82func (r ResourceInstance) ContainingResource() Resource {
83 return r.Resource
84}
85
86func (r ResourceInstance) String() string {
87 if r.Key == NoKey {
88 return r.Resource.String()
89 }
90 return r.Resource.String() + r.Key.String()
91}
92
93func (r ResourceInstance) Equal(o ResourceInstance) bool {
94 return r.String() == o.String()
95}
96
97// Absolute returns an AbsResourceInstance from the receiver and the given module
98// instance address.
99func (r ResourceInstance) Absolute(module ModuleInstance) AbsResourceInstance {
100 return AbsResourceInstance{
101 Module: module,
102 Resource: r,
103 }
104}
105
106// AbsResource is an absolute address for a resource under a given module path.
107type AbsResource struct {
108 targetable
109 Module ModuleInstance
110 Resource Resource
111}
112
113// Resource returns the address of a particular resource within the receiver.
114func (m ModuleInstance) Resource(mode ResourceMode, typeName string, name string) AbsResource {
115 return AbsResource{
116 Module: m,
117 Resource: Resource{
118 Mode: mode,
119 Type: typeName,
120 Name: name,
121 },
122 }
123}
124
125// Instance produces the address for a specific instance of the receiver
126// that is idenfied by the given key.
127func (r AbsResource) Instance(key InstanceKey) AbsResourceInstance {
128 return AbsResourceInstance{
129 Module: r.Module,
130 Resource: r.Resource.Instance(key),
131 }
132}
133
134// TargetContains implements Targetable by returning true if the given other
135// address is either equal to the receiver or is an instance of the
136// receiver.
137func (r AbsResource) TargetContains(other Targetable) bool {
138 switch to := other.(type) {
139
140 case AbsResource:
141 // We'll use our stringification as a cheat-ish way to test for equality.
142 return to.String() == r.String()
143
144 case AbsResourceInstance:
145 return r.TargetContains(to.ContainingResource())
146
147 default:
148 return false
149
150 }
151}
152
153func (r AbsResource) String() string {
154 if len(r.Module) == 0 {
155 return r.Resource.String()
156 }
157 return fmt.Sprintf("%s.%s", r.Module.String(), r.Resource.String())
158}
159
160func (r AbsResource) Equal(o AbsResource) bool {
161 return r.String() == o.String()
162}
163
164// AbsResourceInstance is an absolute address for a resource instance under a
165// given module path.
166type AbsResourceInstance struct {
167 targetable
168 Module ModuleInstance
169 Resource ResourceInstance
170}
171
172// ResourceInstance returns the address of a particular resource instance within the receiver.
173func (m ModuleInstance) ResourceInstance(mode ResourceMode, typeName string, name string, key InstanceKey) AbsResourceInstance {
174 return AbsResourceInstance{
175 Module: m,
176 Resource: ResourceInstance{
177 Resource: Resource{
178 Mode: mode,
179 Type: typeName,
180 Name: name,
181 },
182 Key: key,
183 },
184 }
185}
186
187// ContainingResource returns the address of the resource that contains the
188// receving resource instance. In other words, it discards the key portion
189// of the address to produce an AbsResource value.
190func (r AbsResourceInstance) ContainingResource() AbsResource {
191 return AbsResource{
192 Module: r.Module,
193 Resource: r.Resource.ContainingResource(),
194 }
195}
196
197// TargetContains implements Targetable by returning true if the given other
198// address is equal to the receiver.
199func (r AbsResourceInstance) TargetContains(other Targetable) bool {
200 switch to := other.(type) {
201
202 case AbsResourceInstance:
203 // We'll use our stringification as a cheat-ish way to test for equality.
204 return to.String() == r.String()
205
206 default:
207 return false
208
209 }
210}
211
212func (r AbsResourceInstance) String() string {
213 if len(r.Module) == 0 {
214 return r.Resource.String()
215 }
216 return fmt.Sprintf("%s.%s", r.Module.String(), r.Resource.String())
217}
218
219func (r AbsResourceInstance) Equal(o AbsResourceInstance) bool {
220 return r.String() == o.String()
221}
222
223// Less returns true if the receiver should sort before the given other value
224// in a sorted list of addresses.
225func (r AbsResourceInstance) Less(o AbsResourceInstance) bool {
226 switch {
227
228 case len(r.Module) != len(o.Module):
229 return len(r.Module) < len(o.Module)
230
231 case r.Module.String() != o.Module.String():
232 return r.Module.Less(o.Module)
233
234 case r.Resource.Resource.Mode != o.Resource.Resource.Mode:
235 return r.Resource.Resource.Mode == DataResourceMode
236
237 case r.Resource.Resource.Type != o.Resource.Resource.Type:
238 return r.Resource.Resource.Type < o.Resource.Resource.Type
239
240 case r.Resource.Resource.Name != o.Resource.Resource.Name:
241 return r.Resource.Resource.Name < o.Resource.Resource.Name
242
243 case r.Resource.Key != o.Resource.Key:
244 return InstanceKeyLess(r.Resource.Key, o.Resource.Key)
245
246 default:
247 return false
248
249 }
250}
251
252// ResourceMode defines which lifecycle applies to a given resource. Each
253// resource lifecycle has a slightly different address format.
254type ResourceMode rune
255
256//go:generate stringer -type ResourceMode
257
258const (
259 // InvalidResourceMode is the zero value of ResourceMode and is not
260 // a valid resource mode.
261 InvalidResourceMode ResourceMode = 0
262
263 // ManagedResourceMode indicates a managed resource, as defined by
264 // "resource" blocks in configuration.
265 ManagedResourceMode ResourceMode = 'M'
266
267 // DataResourceMode indicates a data resource, as defined by
268 // "data" blocks in configuration.
269 DataResourceMode ResourceMode = 'D'
270)
diff --git a/vendor/github.com/hashicorp/terraform/addrs/resource_phase.go b/vendor/github.com/hashicorp/terraform/addrs/resource_phase.go
new file mode 100644
index 0000000..9bdbdc4
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/addrs/resource_phase.go
@@ -0,0 +1,105 @@
1package addrs
2
3import "fmt"
4
5// ResourceInstancePhase is a special kind of reference used only internally
6// during graph building to represent resource instances that are in a
7// non-primary state.
8//
9// Graph nodes can declare themselves referenceable via an instance phase
10// or can declare that they reference an instance phase in order to accomodate
11// secondary graph nodes dealing with, for example, destroy actions.
12//
13// This special reference type cannot be accessed directly by end-users, and
14// should never be shown in the UI.
15type ResourceInstancePhase struct {
16 referenceable
17 ResourceInstance ResourceInstance
18 Phase ResourceInstancePhaseType
19}
20
21var _ Referenceable = ResourceInstancePhase{}
22
23// Phase returns a special "phase address" for the receving instance. See the
24// documentation of ResourceInstancePhase for the limited situations where this
25// is intended to be used.
26func (r ResourceInstance) Phase(rpt ResourceInstancePhaseType) ResourceInstancePhase {
27 return ResourceInstancePhase{
28 ResourceInstance: r,
29 Phase: rpt,
30 }
31}
32
33// ContainingResource returns an address for the same phase of the resource
34// that this instance belongs to.
35func (rp ResourceInstancePhase) ContainingResource() ResourcePhase {
36 return rp.ResourceInstance.Resource.Phase(rp.Phase)
37}
38
39func (rp ResourceInstancePhase) String() string {
40 // We use a different separator here than usual to ensure that we'll
41 // never conflict with any non-phased resource instance string. This
42 // is intentionally something that would fail parsing with ParseRef,
43 // because this special address type should never be exposed in the UI.
44 return fmt.Sprintf("%s#%s", rp.ResourceInstance, rp.Phase)
45}
46
47// ResourceInstancePhaseType is an enumeration used with ResourceInstancePhase.
48type ResourceInstancePhaseType string
49
50const (
51 // ResourceInstancePhaseDestroy represents the "destroy" phase of a
52 // resource instance.
53 ResourceInstancePhaseDestroy ResourceInstancePhaseType = "destroy"
54
55 // ResourceInstancePhaseDestroyCBD is similar to ResourceInstancePhaseDestroy
56 // but is used for resources that have "create_before_destroy" set, thus
57 // requiring a different dependency ordering.
58 ResourceInstancePhaseDestroyCBD ResourceInstancePhaseType = "destroy-cbd"
59)
60
61func (rpt ResourceInstancePhaseType) String() string {
62 return string(rpt)
63}
64
65// ResourcePhase is a special kind of reference used only internally
66// during graph building to represent resources that are in a
67// non-primary state.
68//
69// Graph nodes can declare themselves referenceable via a resource phase
70// or can declare that they reference a resource phase in order to accomodate
71// secondary graph nodes dealing with, for example, destroy actions.
72//
73// Since resources (as opposed to instances) aren't actually phased, this
74// address type is used only as an approximation during initial construction
75// of the resource-oriented plan graph, under the assumption that resource
76// instances with ResourceInstancePhase addresses will be created in dynamic
77// subgraphs during the graph walk.
78//
79// This special reference type cannot be accessed directly by end-users, and
80// should never be shown in the UI.
81type ResourcePhase struct {
82 referenceable
83 Resource Resource
84 Phase ResourceInstancePhaseType
85}
86
87var _ Referenceable = ResourcePhase{}
88
89// Phase returns a special "phase address" for the receving instance. See the
90// documentation of ResourceInstancePhase for the limited situations where this
91// is intended to be used.
92func (r Resource) Phase(rpt ResourceInstancePhaseType) ResourcePhase {
93 return ResourcePhase{
94 Resource: r,
95 Phase: rpt,
96 }
97}
98
99func (rp ResourcePhase) String() string {
100 // We use a different separator here than usual to ensure that we'll
101 // never conflict with any non-phased resource instance string. This
102 // is intentionally something that would fail parsing with ParseRef,
103 // because this special address type should never be exposed in the UI.
104 return fmt.Sprintf("%s#%s", rp.Resource, rp.Phase)
105}
diff --git a/vendor/github.com/hashicorp/terraform/addrs/resourcemode_string.go b/vendor/github.com/hashicorp/terraform/addrs/resourcemode_string.go
new file mode 100644
index 0000000..0b5c33f
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/addrs/resourcemode_string.go
@@ -0,0 +1,33 @@
1// Code generated by "stringer -type ResourceMode"; DO NOT EDIT.
2
3package addrs
4
5import "strconv"
6
7func _() {
8 // An "invalid array index" compiler error signifies that the constant values have changed.
9 // Re-run the stringer command to generate them again.
10 var x [1]struct{}
11 _ = x[InvalidResourceMode-0]
12 _ = x[ManagedResourceMode-77]
13 _ = x[DataResourceMode-68]
14}
15
16const (
17 _ResourceMode_name_0 = "InvalidResourceMode"
18 _ResourceMode_name_1 = "DataResourceMode"
19 _ResourceMode_name_2 = "ManagedResourceMode"
20)
21
22func (i ResourceMode) String() string {
23 switch {
24 case i == 0:
25 return _ResourceMode_name_0
26 case i == 68:
27 return _ResourceMode_name_1
28 case i == 77:
29 return _ResourceMode_name_2
30 default:
31 return "ResourceMode(" + strconv.FormatInt(int64(i), 10) + ")"
32 }
33}
diff --git a/vendor/github.com/hashicorp/terraform/addrs/self.go b/vendor/github.com/hashicorp/terraform/addrs/self.go
new file mode 100644
index 0000000..7f24eaf
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/addrs/self.go
@@ -0,0 +1,14 @@
1package addrs
2
3// Self is the address of the special object "self" that behaves as an alias
4// for a containing object currently in scope.
5const Self selfT = 0
6
7type selfT int
8
9func (s selfT) referenceableSigil() {
10}
11
12func (s selfT) String() string {
13 return "self"
14}
diff --git a/vendor/github.com/hashicorp/terraform/addrs/targetable.go b/vendor/github.com/hashicorp/terraform/addrs/targetable.go
new file mode 100644
index 0000000..16819a5
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/addrs/targetable.go
@@ -0,0 +1,26 @@
1package addrs
2
3// Targetable is an interface implemented by all address types that can be
4// used as "targets" for selecting sub-graphs of a graph.
5type Targetable interface {
6 targetableSigil()
7
8 // TargetContains returns true if the receiver is considered to contain
9 // the given other address. Containment, for the purpose of targeting,
10 // means that if a container address is targeted then all of the
11 // addresses within it are also implicitly targeted.
12 //
13 // A targetable address always contains at least itself.
14 TargetContains(other Targetable) bool
15
16 // String produces a string representation of the address that could be
17 // parsed as a HCL traversal and passed to ParseTarget to produce an
18 // identical result.
19 String() string
20}
21
22type targetable struct {
23}
24
25func (r targetable) targetableSigil() {
26}
diff --git a/vendor/github.com/hashicorp/terraform/addrs/terraform_attr.go b/vendor/github.com/hashicorp/terraform/addrs/terraform_attr.go
new file mode 100644
index 0000000..a880182
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/addrs/terraform_attr.go
@@ -0,0 +1,12 @@
1package addrs
2
3// TerraformAttr is the address of an attribute of the "terraform" object in
4// the interpolation scope, like "terraform.workspace".
5type TerraformAttr struct {
6 referenceable
7 Name string
8}
9
10func (ta TerraformAttr) String() string {
11 return "terraform." + ta.Name
12}