diff options
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/addrs')
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 @@ | |||
1 | package addrs | ||
2 | |||
3 | // CountAttr is the address of an attribute of the "count" object in | ||
4 | // the interpolation scope, like "count.index". | ||
5 | type CountAttr struct { | ||
6 | referenceable | ||
7 | Name string | ||
8 | } | ||
9 | |||
10 | func (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. | ||
17 | package 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 @@ | |||
1 | package addrs | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | ) | ||
6 | |||
7 | // InputVariable is the address of an input variable. | ||
8 | type InputVariable struct { | ||
9 | referenceable | ||
10 | Name string | ||
11 | } | ||
12 | |||
13 | func (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. | ||
19 | type 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. | ||
26 | func (m ModuleInstance) InputVariable(name string) AbsInputVariableInstance { | ||
27 | return AbsInputVariableInstance{ | ||
28 | Module: m, | ||
29 | Variable: InputVariable{ | ||
30 | Name: name, | ||
31 | }, | ||
32 | } | ||
33 | } | ||
34 | |||
35 | func (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 @@ | |||
1 | package addrs | ||
2 | |||
3 | import ( | ||
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. | ||
18 | type 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. | ||
30 | func 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. | ||
45 | var 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. | ||
50 | type IntKey int | ||
51 | |||
52 | func (k IntKey) instanceKeySigil() { | ||
53 | } | ||
54 | |||
55 | func (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. | ||
61 | type StringKey string | ||
62 | |||
63 | func (k StringKey) instanceKeySigil() { | ||
64 | } | ||
65 | |||
66 | func (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. | ||
74 | func 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 | |||
102 | func 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. | ||
117 | type InstanceKeyType rune | ||
118 | |||
119 | const ( | ||
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 @@ | |||
1 | package addrs | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | ) | ||
6 | |||
7 | // LocalValue is the address of a local value. | ||
8 | type LocalValue struct { | ||
9 | referenceable | ||
10 | Name string | ||
11 | } | ||
12 | |||
13 | func (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. | ||
19 | func (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. | ||
27 | type 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. | ||
34 | func (m ModuleInstance) LocalValue(name string) AbsLocalValue { | ||
35 | return AbsLocalValue{ | ||
36 | Module: m, | ||
37 | LocalValue: LocalValue{ | ||
38 | Name: name, | ||
39 | }, | ||
40 | } | ||
41 | } | ||
42 | |||
43 | func (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 @@ | |||
1 | package addrs | ||
2 | |||
3 | import ( | ||
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. | ||
17 | type 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. | ||
24 | var RootModule Module | ||
25 | |||
26 | // IsRoot returns true if the receiver is the address of the root module, | ||
27 | // or false otherwise. | ||
28 | func (m Module) IsRoot() bool { | ||
29 | return len(m) == 0 | ||
30 | } | ||
31 | |||
32 | func (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. | ||
41 | func (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). | ||
49 | func (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. | ||
66 | func (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 @@ | |||
1 | package addrs | ||
2 | |||
3 | import ( | ||
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. | ||
12 | type ModuleCall struct { | ||
13 | referenceable | ||
14 | Name string | ||
15 | } | ||
16 | |||
17 | func (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. | ||
23 | func (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. | ||
33 | type ModuleCallInstance struct { | ||
34 | referenceable | ||
35 | Call ModuleCall | ||
36 | Key InstanceKey | ||
37 | } | ||
38 | |||
39 | func (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. | ||
50 | func (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. | ||
56 | func (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. | ||
65 | type ModuleCallOutput struct { | ||
66 | referenceable | ||
67 | Call ModuleCallInstance | ||
68 | Name string | ||
69 | } | ||
70 | |||
71 | func (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. | ||
78 | func (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 @@ | |||
1 | package addrs | ||
2 | |||
3 | import ( | ||
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. | ||
23 | type ModuleInstance []ModuleInstanceStep | ||
24 | |||
25 | var ( | ||
26 | _ Targetable = ModuleInstance(nil) | ||
27 | ) | ||
28 | |||
29 | func 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. | ||
66 | func 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 | |||
80 | func 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. | ||
203 | func (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. | ||
213 | type 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. | ||
220 | var RootModuleInstance ModuleInstance | ||
221 | |||
222 | // IsRoot returns true if the receiver is the address of the root module instance, | ||
223 | // or false otherwise. | ||
224 | func (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. | ||
230 | func (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). | ||
241 | func (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. | ||
252 | func (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. | ||
269 | func (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. | ||
275 | func (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:]. | ||
300 | func (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. | ||
310 | func (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. | ||
343 | func (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. | ||
366 | func (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. | ||
384 | func (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 | |||
413 | func (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 @@ | |||
1 | package addrs | ||
2 | |||
3 | import ( | ||
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. | ||
14 | type OutputValue struct { | ||
15 | Name string | ||
16 | } | ||
17 | |||
18 | func (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. | ||
24 | func (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. | ||
36 | type 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. | ||
43 | func (m ModuleInstance) OutputValue(name string) AbsOutputValue { | ||
44 | return AbsOutputValue{ | ||
45 | Module: m, | ||
46 | OutputValue: OutputValue{ | ||
47 | Name: name, | ||
48 | }, | ||
49 | } | ||
50 | } | ||
51 | |||
52 | func (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. | ||
65 | func (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 @@ | |||
1 | package addrs | ||
2 | |||
3 | import ( | ||
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. | ||
13 | type 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. | ||
30 | func 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. | ||
58 | func 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 | |||
72 | func 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 | |||
219 | func 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 | |||
313 | func 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 @@ | |||
1 | package addrs | ||
2 | |||
3 | import ( | ||
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. | ||
13 | type 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. | ||
27 | func 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. | ||
158 | func 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. | ||
180 | func 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. | ||
236 | func 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. | ||
259 | func 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. | ||
306 | func 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 @@ | |||
1 | package addrs | ||
2 | |||
3 | // PathAttr is the address of an attribute of the "path" object in | ||
4 | // the interpolation scope, like "path.module". | ||
5 | type PathAttr struct { | ||
6 | referenceable | ||
7 | Name string | ||
8 | } | ||
9 | |||
10 | func (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 @@ | |||
1 | package addrs | ||
2 | |||
3 | import ( | ||
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. | ||
13 | type 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. | ||
23 | func 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. | ||
41 | func 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. | ||
93 | func 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. | ||
109 | func (pc ProviderConfig) Absolute(module ModuleInstance) AbsProviderConfig { | ||
110 | return AbsProviderConfig{ | ||
111 | Module: module, | ||
112 | ProviderConfig: pc, | ||
113 | } | ||
114 | } | ||
115 | |||
116 | func (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. | ||
131 | func (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. | ||
140 | type 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. | ||
159 | func 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. | ||
227 | func 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. | ||
243 | func (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. | ||
254 | func (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. | ||
275 | func (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 | |||
292 | func (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 @@ | |||
1 | package addrs | ||
2 | |||
3 | // Referenceable is an interface implemented by all address types that can | ||
4 | // appear as references in configuration language expressions. | ||
5 | type 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 | |||
16 | type referenceable struct { | ||
17 | } | ||
18 | |||
19 | func (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 @@ | |||
1 | package addrs | ||
2 | |||
3 | import ( | ||
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". | ||
11 | type Resource struct { | ||
12 | referenceable | ||
13 | Mode ResourceMode | ||
14 | Type string | ||
15 | Name string | ||
16 | } | ||
17 | |||
18 | func (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 | |||
31 | func (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. | ||
37 | func (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. | ||
46 | func (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. | ||
63 | func (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. | ||
76 | type ResourceInstance struct { | ||
77 | referenceable | ||
78 | Resource Resource | ||
79 | Key InstanceKey | ||
80 | } | ||
81 | |||
82 | func (r ResourceInstance) ContainingResource() Resource { | ||
83 | return r.Resource | ||
84 | } | ||
85 | |||
86 | func (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 | |||
93 | func (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. | ||
99 | func (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. | ||
107 | type AbsResource struct { | ||
108 | targetable | ||
109 | Module ModuleInstance | ||
110 | Resource Resource | ||
111 | } | ||
112 | |||
113 | // Resource returns the address of a particular resource within the receiver. | ||
114 | func (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. | ||
127 | func (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. | ||
137 | func (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 | |||
153 | func (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 | |||
160 | func (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. | ||
166 | type 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. | ||
173 | func (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. | ||
190 | func (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. | ||
199 | func (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 | |||
212 | func (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 | |||
219 | func (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. | ||
225 | func (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. | ||
254 | type ResourceMode rune | ||
255 | |||
256 | //go:generate stringer -type ResourceMode | ||
257 | |||
258 | const ( | ||
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 @@ | |||
1 | package addrs | ||
2 | |||
3 | import "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. | ||
15 | type ResourceInstancePhase struct { | ||
16 | referenceable | ||
17 | ResourceInstance ResourceInstance | ||
18 | Phase ResourceInstancePhaseType | ||
19 | } | ||
20 | |||
21 | var _ 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. | ||
26 | func (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. | ||
35 | func (rp ResourceInstancePhase) ContainingResource() ResourcePhase { | ||
36 | return rp.ResourceInstance.Resource.Phase(rp.Phase) | ||
37 | } | ||
38 | |||
39 | func (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. | ||
48 | type ResourceInstancePhaseType string | ||
49 | |||
50 | const ( | ||
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 | |||
61 | func (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. | ||
81 | type ResourcePhase struct { | ||
82 | referenceable | ||
83 | Resource Resource | ||
84 | Phase ResourceInstancePhaseType | ||
85 | } | ||
86 | |||
87 | var _ 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. | ||
92 | func (r Resource) Phase(rpt ResourceInstancePhaseType) ResourcePhase { | ||
93 | return ResourcePhase{ | ||
94 | Resource: r, | ||
95 | Phase: rpt, | ||
96 | } | ||
97 | } | ||
98 | |||
99 | func (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 | |||
3 | package addrs | ||
4 | |||
5 | import "strconv" | ||
6 | |||
7 | func _() { | ||
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 | |||
16 | const ( | ||
17 | _ResourceMode_name_0 = "InvalidResourceMode" | ||
18 | _ResourceMode_name_1 = "DataResourceMode" | ||
19 | _ResourceMode_name_2 = "ManagedResourceMode" | ||
20 | ) | ||
21 | |||
22 | func (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 @@ | |||
1 | package 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. | ||
5 | const Self selfT = 0 | ||
6 | |||
7 | type selfT int | ||
8 | |||
9 | func (s selfT) referenceableSigil() { | ||
10 | } | ||
11 | |||
12 | func (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 @@ | |||
1 | package 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. | ||
5 | type 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 | |||
22 | type targetable struct { | ||
23 | } | ||
24 | |||
25 | func (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 @@ | |||
1 | package addrs | ||
2 | |||
3 | // TerraformAttr is the address of an attribute of the "terraform" object in | ||
4 | // the interpolation scope, like "terraform.workspace". | ||
5 | type TerraformAttr struct { | ||
6 | referenceable | ||
7 | Name string | ||
8 | } | ||
9 | |||
10 | func (ta TerraformAttr) String() string { | ||
11 | return "terraform." + ta.Name | ||
12 | } | ||