]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/hashicorp/terraform/configs/module_call.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / configs / module_call.go
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 }