aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/terraform/configs/synth_body.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/configs/synth_body.go')
-rw-r--r--vendor/github.com/hashicorp/terraform/configs/synth_body.go118
1 files changed, 118 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/configs/synth_body.go b/vendor/github.com/hashicorp/terraform/configs/synth_body.go
new file mode 100644
index 0000000..3ae1bff
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/configs/synth_body.go
@@ -0,0 +1,118 @@
1package configs
2
3import (
4 "fmt"
5
6 "github.com/hashicorp/hcl2/hcl"
7 "github.com/hashicorp/hcl2/hcl/hclsyntax"
8 "github.com/zclconf/go-cty/cty"
9)
10
11// SynthBody produces a synthetic hcl.Body that behaves as if it had attributes
12// corresponding to the elements given in the values map.
13//
14// This is useful in situations where, for example, values provided on the
15// command line can override values given in configuration, using MergeBodies.
16//
17// The given filename is used in case any diagnostics are returned. Since
18// the created body is synthetic, it is likely that this will not be a "real"
19// filename. For example, if from a command line argument it could be
20// a representation of that argument's name, such as "-var=...".
21func SynthBody(filename string, values map[string]cty.Value) hcl.Body {
22 return synthBody{
23 Filename: filename,
24 Values: values,
25 }
26}
27
28type synthBody struct {
29 Filename string
30 Values map[string]cty.Value
31}
32
33func (b synthBody) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostics) {
34 content, remain, diags := b.PartialContent(schema)
35 remainS := remain.(synthBody)
36 for name := range remainS.Values {
37 diags = append(diags, &hcl.Diagnostic{
38 Severity: hcl.DiagError,
39 Summary: "Unsupported attribute",
40 Detail: fmt.Sprintf("An attribute named %q is not expected here.", name),
41 Subject: b.synthRange().Ptr(),
42 })
43 }
44 return content, diags
45}
46
47func (b synthBody) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics) {
48 var diags hcl.Diagnostics
49 content := &hcl.BodyContent{
50 Attributes: make(hcl.Attributes),
51 MissingItemRange: b.synthRange(),
52 }
53
54 remainValues := make(map[string]cty.Value)
55 for attrName, val := range b.Values {
56 remainValues[attrName] = val
57 }
58
59 for _, attrS := range schema.Attributes {
60 delete(remainValues, attrS.Name)
61 val, defined := b.Values[attrS.Name]
62 if !defined {
63 if attrS.Required {
64 diags = append(diags, &hcl.Diagnostic{
65 Severity: hcl.DiagError,
66 Summary: "Missing required attribute",
67 Detail: fmt.Sprintf("The attribute %q is required, but no definition was found.", attrS.Name),
68 Subject: b.synthRange().Ptr(),
69 })
70 }
71 continue
72 }
73 content.Attributes[attrS.Name] = b.synthAttribute(attrS.Name, val)
74 }
75
76 // We just ignore blocks altogether, because this body type never has
77 // nested blocks.
78
79 remain := synthBody{
80 Filename: b.Filename,
81 Values: remainValues,
82 }
83
84 return content, remain, diags
85}
86
87func (b synthBody) JustAttributes() (hcl.Attributes, hcl.Diagnostics) {
88 ret := make(hcl.Attributes)
89 for name, val := range b.Values {
90 ret[name] = b.synthAttribute(name, val)
91 }
92 return ret, nil
93}
94
95func (b synthBody) MissingItemRange() hcl.Range {
96 return b.synthRange()
97}
98
99func (b synthBody) synthAttribute(name string, val cty.Value) *hcl.Attribute {
100 rng := b.synthRange()
101 return &hcl.Attribute{
102 Name: name,
103 Expr: &hclsyntax.LiteralValueExpr{
104 Val: val,
105 SrcRange: rng,
106 },
107 NameRange: rng,
108 Range: rng,
109 }
110}
111
112func (b synthBody) synthRange() hcl.Range {
113 return hcl.Range{
114 Filename: b.Filename,
115 Start: hcl.Pos{Line: 1, Column: 1},
116 End: hcl.Pos{Line: 1, Column: 1},
117 }
118}