diff options
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/configs/module_call.go')
-rw-r--r-- | vendor/github.com/hashicorp/terraform/configs/module_call.go | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/configs/module_call.go b/vendor/github.com/hashicorp/terraform/configs/module_call.go new file mode 100644 index 0000000..8c3ba67 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/configs/module_call.go | |||
@@ -0,0 +1,188 @@ | |||
1 | package configs | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | |||
6 | "github.com/hashicorp/hcl2/gohcl" | ||
7 | "github.com/hashicorp/hcl2/hcl" | ||
8 | "github.com/hashicorp/hcl2/hcl/hclsyntax" | ||
9 | ) | ||
10 | |||
11 | // ModuleCall represents a "module" block in a module or file. | ||
12 | type ModuleCall struct { | ||
13 | Name string | ||
14 | |||
15 | SourceAddr string | ||
16 | SourceAddrRange hcl.Range | ||
17 | SourceSet bool | ||
18 | |||
19 | Config hcl.Body | ||
20 | |||
21 | Version VersionConstraint | ||
22 | |||
23 | Count hcl.Expression | ||
24 | ForEach hcl.Expression | ||
25 | |||
26 | Providers []PassedProviderConfig | ||
27 | |||
28 | DependsOn []hcl.Traversal | ||
29 | |||
30 | DeclRange hcl.Range | ||
31 | } | ||
32 | |||
33 | func decodeModuleBlock(block *hcl.Block, override bool) (*ModuleCall, hcl.Diagnostics) { | ||
34 | mc := &ModuleCall{ | ||
35 | Name: block.Labels[0], | ||
36 | DeclRange: block.DefRange, | ||
37 | } | ||
38 | |||
39 | schema := moduleBlockSchema | ||
40 | if override { | ||
41 | schema = schemaForOverrides(schema) | ||
42 | } | ||
43 | |||
44 | content, remain, diags := block.Body.PartialContent(schema) | ||
45 | mc.Config = remain | ||
46 | |||
47 | if !hclsyntax.ValidIdentifier(mc.Name) { | ||
48 | diags = append(diags, &hcl.Diagnostic{ | ||
49 | Severity: hcl.DiagError, | ||
50 | Summary: "Invalid module instance name", | ||
51 | Detail: badIdentifierDetail, | ||
52 | Subject: &block.LabelRanges[0], | ||
53 | }) | ||
54 | } | ||
55 | |||
56 | if attr, exists := content.Attributes["source"]; exists { | ||
57 | valDiags := gohcl.DecodeExpression(attr.Expr, nil, &mc.SourceAddr) | ||
58 | diags = append(diags, valDiags...) | ||
59 | mc.SourceAddrRange = attr.Expr.Range() | ||
60 | mc.SourceSet = true | ||
61 | } | ||
62 | |||
63 | if attr, exists := content.Attributes["version"]; exists { | ||
64 | var versionDiags hcl.Diagnostics | ||
65 | mc.Version, versionDiags = decodeVersionConstraint(attr) | ||
66 | diags = append(diags, versionDiags...) | ||
67 | } | ||
68 | |||
69 | if attr, exists := content.Attributes["count"]; exists { | ||
70 | mc.Count = attr.Expr | ||
71 | |||
72 | // We currently parse this, but don't yet do anything with it. | ||
73 | diags = append(diags, &hcl.Diagnostic{ | ||
74 | Severity: hcl.DiagError, | ||
75 | Summary: "Reserved argument name in module block", | ||
76 | Detail: fmt.Sprintf("The name %q is reserved for use in a future version of Terraform.", attr.Name), | ||
77 | Subject: &attr.NameRange, | ||
78 | }) | ||
79 | } | ||
80 | |||
81 | if attr, exists := content.Attributes["for_each"]; exists { | ||
82 | mc.ForEach = attr.Expr | ||
83 | |||
84 | // We currently parse this, but don't yet do anything with it. | ||
85 | diags = append(diags, &hcl.Diagnostic{ | ||
86 | Severity: hcl.DiagError, | ||
87 | Summary: "Reserved argument name in module block", | ||
88 | Detail: fmt.Sprintf("The name %q is reserved for use in a future version of Terraform.", attr.Name), | ||
89 | Subject: &attr.NameRange, | ||
90 | }) | ||
91 | } | ||
92 | |||
93 | if attr, exists := content.Attributes["depends_on"]; exists { | ||
94 | deps, depsDiags := decodeDependsOn(attr) | ||
95 | diags = append(diags, depsDiags...) | ||
96 | mc.DependsOn = append(mc.DependsOn, deps...) | ||
97 | |||
98 | // We currently parse this, but don't yet do anything with it. | ||
99 | diags = append(diags, &hcl.Diagnostic{ | ||
100 | Severity: hcl.DiagError, | ||
101 | Summary: "Reserved argument name in module block", | ||
102 | Detail: fmt.Sprintf("The name %q is reserved for use in a future version of Terraform.", attr.Name), | ||
103 | Subject: &attr.NameRange, | ||
104 | }) | ||
105 | } | ||
106 | |||
107 | if attr, exists := content.Attributes["providers"]; exists { | ||
108 | seen := make(map[string]hcl.Range) | ||
109 | pairs, pDiags := hcl.ExprMap(attr.Expr) | ||
110 | diags = append(diags, pDiags...) | ||
111 | for _, pair := range pairs { | ||
112 | key, keyDiags := decodeProviderConfigRef(pair.Key, "providers") | ||
113 | diags = append(diags, keyDiags...) | ||
114 | value, valueDiags := decodeProviderConfigRef(pair.Value, "providers") | ||
115 | diags = append(diags, valueDiags...) | ||
116 | if keyDiags.HasErrors() || valueDiags.HasErrors() { | ||
117 | continue | ||
118 | } | ||
119 | |||
120 | matchKey := key.String() | ||
121 | if prev, exists := seen[matchKey]; exists { | ||
122 | diags = append(diags, &hcl.Diagnostic{ | ||
123 | Severity: hcl.DiagError, | ||
124 | Summary: "Duplicate provider address", | ||
125 | Detail: fmt.Sprintf("A provider configuration was already passed to %s at %s. Each child provider configuration can be assigned only once.", matchKey, prev), | ||
126 | Subject: pair.Value.Range().Ptr(), | ||
127 | }) | ||
128 | continue | ||
129 | } | ||
130 | |||
131 | rng := hcl.RangeBetween(pair.Key.Range(), pair.Value.Range()) | ||
132 | seen[matchKey] = rng | ||
133 | mc.Providers = append(mc.Providers, PassedProviderConfig{ | ||
134 | InChild: key, | ||
135 | InParent: value, | ||
136 | }) | ||
137 | } | ||
138 | } | ||
139 | |||
140 | // Reserved block types (all of them) | ||
141 | for _, block := range content.Blocks { | ||
142 | diags = append(diags, &hcl.Diagnostic{ | ||
143 | Severity: hcl.DiagError, | ||
144 | Summary: "Reserved block type name in module block", | ||
145 | Detail: fmt.Sprintf("The block type name %q is reserved for use by Terraform in a future version.", block.Type), | ||
146 | Subject: &block.TypeRange, | ||
147 | }) | ||
148 | } | ||
149 | |||
150 | return mc, diags | ||
151 | } | ||
152 | |||
153 | // PassedProviderConfig represents a provider config explicitly passed down to | ||
154 | // a child module, possibly giving it a new local address in the process. | ||
155 | type PassedProviderConfig struct { | ||
156 | InChild *ProviderConfigRef | ||
157 | InParent *ProviderConfigRef | ||
158 | } | ||
159 | |||
160 | var moduleBlockSchema = &hcl.BodySchema{ | ||
161 | Attributes: []hcl.AttributeSchema{ | ||
162 | { | ||
163 | Name: "source", | ||
164 | Required: true, | ||
165 | }, | ||
166 | { | ||
167 | Name: "version", | ||
168 | }, | ||
169 | { | ||
170 | Name: "count", | ||
171 | }, | ||
172 | { | ||
173 | Name: "for_each", | ||
174 | }, | ||
175 | { | ||
176 | Name: "depends_on", | ||
177 | }, | ||
178 | { | ||
179 | Name: "providers", | ||
180 | }, | ||
181 | }, | ||
182 | Blocks: []hcl.BlockHeaderSchema{ | ||
183 | // These are all reserved for future use. | ||
184 | {Type: "lifecycle"}, | ||
185 | {Type: "locals"}, | ||
186 | {Type: "provider", LabelNames: []string{"type"}}, | ||
187 | }, | ||
188 | } | ||