diff options
author | Nathan Dench <ndenc2@gmail.com> | 2019-05-24 15:16:44 +1000 |
---|---|---|
committer | Nathan Dench <ndenc2@gmail.com> | 2019-05-24 15:16:44 +1000 |
commit | 107c1cdb09c575aa2f61d97f48d8587eb6bada4c (patch) | |
tree | ca7d008643efc555c388baeaf1d986e0b6b3e28c /vendor/github.com/hashicorp/hcl2/ext/dynblock/expand_spec.go | |
parent | 844b5a68d8af4791755b8f0ad293cc99f5959183 (diff) | |
download | terraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.tar.gz terraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.tar.zst terraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.zip |
Upgrade to 0.12
Diffstat (limited to 'vendor/github.com/hashicorp/hcl2/ext/dynblock/expand_spec.go')
-rw-r--r-- | vendor/github.com/hashicorp/hcl2/ext/dynblock/expand_spec.go | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/hcl2/ext/dynblock/expand_spec.go b/vendor/github.com/hashicorp/hcl2/ext/dynblock/expand_spec.go new file mode 100644 index 0000000..41c0be2 --- /dev/null +++ b/vendor/github.com/hashicorp/hcl2/ext/dynblock/expand_spec.go | |||
@@ -0,0 +1,215 @@ | |||
1 | package dynblock | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | |||
6 | "github.com/hashicorp/hcl2/hcl" | ||
7 | "github.com/zclconf/go-cty/cty" | ||
8 | "github.com/zclconf/go-cty/cty/convert" | ||
9 | ) | ||
10 | |||
11 | type expandSpec struct { | ||
12 | blockType string | ||
13 | blockTypeRange hcl.Range | ||
14 | defRange hcl.Range | ||
15 | forEachVal cty.Value | ||
16 | iteratorName string | ||
17 | labelExprs []hcl.Expression | ||
18 | contentBody hcl.Body | ||
19 | inherited map[string]*iteration | ||
20 | } | ||
21 | |||
22 | func (b *expandBody) decodeSpec(blockS *hcl.BlockHeaderSchema, rawSpec *hcl.Block) (*expandSpec, hcl.Diagnostics) { | ||
23 | var diags hcl.Diagnostics | ||
24 | |||
25 | var schema *hcl.BodySchema | ||
26 | if len(blockS.LabelNames) != 0 { | ||
27 | schema = dynamicBlockBodySchemaLabels | ||
28 | } else { | ||
29 | schema = dynamicBlockBodySchemaNoLabels | ||
30 | } | ||
31 | |||
32 | specContent, specDiags := rawSpec.Body.Content(schema) | ||
33 | diags = append(diags, specDiags...) | ||
34 | if specDiags.HasErrors() { | ||
35 | return nil, diags | ||
36 | } | ||
37 | |||
38 | //// for_each attribute | ||
39 | |||
40 | eachAttr := specContent.Attributes["for_each"] | ||
41 | eachVal, eachDiags := eachAttr.Expr.Value(b.forEachCtx) | ||
42 | diags = append(diags, eachDiags...) | ||
43 | |||
44 | if !eachVal.CanIterateElements() && eachVal.Type() != cty.DynamicPseudoType { | ||
45 | // We skip this error for DynamicPseudoType because that means we either | ||
46 | // have a null (which is checked immediately below) or an unknown | ||
47 | // (which is handled in the expandBody Content methods). | ||
48 | diags = append(diags, &hcl.Diagnostic{ | ||
49 | Severity: hcl.DiagError, | ||
50 | Summary: "Invalid dynamic for_each value", | ||
51 | Detail: fmt.Sprintf("Cannot use a %s value in for_each. An iterable collection is required.", eachVal.Type().FriendlyName()), | ||
52 | Subject: eachAttr.Expr.Range().Ptr(), | ||
53 | Expression: eachAttr.Expr, | ||
54 | EvalContext: b.forEachCtx, | ||
55 | }) | ||
56 | return nil, diags | ||
57 | } | ||
58 | if eachVal.IsNull() { | ||
59 | diags = append(diags, &hcl.Diagnostic{ | ||
60 | Severity: hcl.DiagError, | ||
61 | Summary: "Invalid dynamic for_each value", | ||
62 | Detail: "Cannot use a null value in for_each.", | ||
63 | Subject: eachAttr.Expr.Range().Ptr(), | ||
64 | Expression: eachAttr.Expr, | ||
65 | EvalContext: b.forEachCtx, | ||
66 | }) | ||
67 | return nil, diags | ||
68 | } | ||
69 | |||
70 | //// iterator attribute | ||
71 | |||
72 | iteratorName := blockS.Type | ||
73 | if iteratorAttr := specContent.Attributes["iterator"]; iteratorAttr != nil { | ||
74 | itTraversal, itDiags := hcl.AbsTraversalForExpr(iteratorAttr.Expr) | ||
75 | diags = append(diags, itDiags...) | ||
76 | if itDiags.HasErrors() { | ||
77 | return nil, diags | ||
78 | } | ||
79 | |||
80 | if len(itTraversal) != 1 { | ||
81 | diags = append(diags, &hcl.Diagnostic{ | ||
82 | Severity: hcl.DiagError, | ||
83 | Summary: "Invalid dynamic iterator name", | ||
84 | Detail: "Dynamic iterator must be a single variable name.", | ||
85 | Subject: itTraversal.SourceRange().Ptr(), | ||
86 | }) | ||
87 | return nil, diags | ||
88 | } | ||
89 | |||
90 | iteratorName = itTraversal.RootName() | ||
91 | } | ||
92 | |||
93 | var labelExprs []hcl.Expression | ||
94 | if labelsAttr := specContent.Attributes["labels"]; labelsAttr != nil { | ||
95 | var labelDiags hcl.Diagnostics | ||
96 | labelExprs, labelDiags = hcl.ExprList(labelsAttr.Expr) | ||
97 | diags = append(diags, labelDiags...) | ||
98 | if labelDiags.HasErrors() { | ||
99 | return nil, diags | ||
100 | } | ||
101 | |||
102 | if len(labelExprs) > len(blockS.LabelNames) { | ||
103 | diags = append(diags, &hcl.Diagnostic{ | ||
104 | Severity: hcl.DiagError, | ||
105 | Summary: "Extraneous dynamic block label", | ||
106 | Detail: fmt.Sprintf("Blocks of type %q require %d label(s).", blockS.Type, len(blockS.LabelNames)), | ||
107 | Subject: labelExprs[len(blockS.LabelNames)].Range().Ptr(), | ||
108 | }) | ||
109 | return nil, diags | ||
110 | } else if len(labelExprs) < len(blockS.LabelNames) { | ||
111 | diags = append(diags, &hcl.Diagnostic{ | ||
112 | Severity: hcl.DiagError, | ||
113 | Summary: "Insufficient dynamic block labels", | ||
114 | Detail: fmt.Sprintf("Blocks of type %q require %d label(s).", blockS.Type, len(blockS.LabelNames)), | ||
115 | Subject: labelsAttr.Expr.Range().Ptr(), | ||
116 | }) | ||
117 | return nil, diags | ||
118 | } | ||
119 | } | ||
120 | |||
121 | // Since our schema requests only blocks of type "content", we can assume | ||
122 | // that all entries in specContent.Blocks are content blocks. | ||
123 | if len(specContent.Blocks) == 0 { | ||
124 | diags = append(diags, &hcl.Diagnostic{ | ||
125 | Severity: hcl.DiagError, | ||
126 | Summary: "Missing dynamic content block", | ||
127 | Detail: "A dynamic block must have a nested block of type \"content\" to describe the body of each generated block.", | ||
128 | Subject: &specContent.MissingItemRange, | ||
129 | }) | ||
130 | return nil, diags | ||
131 | } | ||
132 | if len(specContent.Blocks) > 1 { | ||
133 | diags = append(diags, &hcl.Diagnostic{ | ||
134 | Severity: hcl.DiagError, | ||
135 | Summary: "Extraneous dynamic content block", | ||
136 | Detail: "Only one nested content block is allowed for each dynamic block.", | ||
137 | Subject: &specContent.Blocks[1].DefRange, | ||
138 | }) | ||
139 | return nil, diags | ||
140 | } | ||
141 | |||
142 | return &expandSpec{ | ||
143 | blockType: blockS.Type, | ||
144 | blockTypeRange: rawSpec.LabelRanges[0], | ||
145 | defRange: rawSpec.DefRange, | ||
146 | forEachVal: eachVal, | ||
147 | iteratorName: iteratorName, | ||
148 | labelExprs: labelExprs, | ||
149 | contentBody: specContent.Blocks[0].Body, | ||
150 | }, diags | ||
151 | } | ||
152 | |||
153 | func (s *expandSpec) newBlock(i *iteration, ctx *hcl.EvalContext) (*hcl.Block, hcl.Diagnostics) { | ||
154 | var diags hcl.Diagnostics | ||
155 | var labels []string | ||
156 | var labelRanges []hcl.Range | ||
157 | lCtx := i.EvalContext(ctx) | ||
158 | for _, labelExpr := range s.labelExprs { | ||
159 | labelVal, labelDiags := labelExpr.Value(lCtx) | ||
160 | diags = append(diags, labelDiags...) | ||
161 | if labelDiags.HasErrors() { | ||
162 | return nil, diags | ||
163 | } | ||
164 | |||
165 | var convErr error | ||
166 | labelVal, convErr = convert.Convert(labelVal, cty.String) | ||
167 | if convErr != nil { | ||
168 | diags = append(diags, &hcl.Diagnostic{ | ||
169 | Severity: hcl.DiagError, | ||
170 | Summary: "Invalid dynamic block label", | ||
171 | Detail: fmt.Sprintf("Cannot use this value as a dynamic block label: %s.", convErr), | ||
172 | Subject: labelExpr.Range().Ptr(), | ||
173 | Expression: labelExpr, | ||
174 | EvalContext: lCtx, | ||
175 | }) | ||
176 | return nil, diags | ||
177 | } | ||
178 | if labelVal.IsNull() { | ||
179 | diags = append(diags, &hcl.Diagnostic{ | ||
180 | Severity: hcl.DiagError, | ||
181 | Summary: "Invalid dynamic block label", | ||
182 | Detail: "Cannot use a null value as a dynamic block label.", | ||
183 | Subject: labelExpr.Range().Ptr(), | ||
184 | Expression: labelExpr, | ||
185 | EvalContext: lCtx, | ||
186 | }) | ||
187 | return nil, diags | ||
188 | } | ||
189 | if !labelVal.IsKnown() { | ||
190 | diags = append(diags, &hcl.Diagnostic{ | ||
191 | Severity: hcl.DiagError, | ||
192 | Summary: "Invalid dynamic block label", | ||
193 | Detail: "This value is not yet known. Dynamic block labels must be immediately-known values.", | ||
194 | Subject: labelExpr.Range().Ptr(), | ||
195 | Expression: labelExpr, | ||
196 | EvalContext: lCtx, | ||
197 | }) | ||
198 | return nil, diags | ||
199 | } | ||
200 | |||
201 | labels = append(labels, labelVal.AsString()) | ||
202 | labelRanges = append(labelRanges, labelExpr.Range()) | ||
203 | } | ||
204 | |||
205 | block := &hcl.Block{ | ||
206 | Type: s.blockType, | ||
207 | TypeRange: s.blockTypeRange, | ||
208 | Labels: labels, | ||
209 | LabelRanges: labelRanges, | ||
210 | DefRange: s.defRange, | ||
211 | Body: s.contentBody, | ||
212 | } | ||
213 | |||
214 | return block, diags | ||
215 | } | ||