diff options
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/plugin/convert/diagnostics.go')
-rw-r--r-- | vendor/github.com/hashicorp/terraform/plugin/convert/diagnostics.go | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/plugin/convert/diagnostics.go b/vendor/github.com/hashicorp/terraform/plugin/convert/diagnostics.go new file mode 100644 index 0000000..51cb2fe --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/plugin/convert/diagnostics.go | |||
@@ -0,0 +1,132 @@ | |||
1 | package convert | ||
2 | |||
3 | import ( | ||
4 | proto "github.com/hashicorp/terraform/internal/tfplugin5" | ||
5 | "github.com/hashicorp/terraform/tfdiags" | ||
6 | "github.com/zclconf/go-cty/cty" | ||
7 | ) | ||
8 | |||
9 | // WarnsAndErrorsToProto converts the warnings and errors return by the legacy | ||
10 | // provider to protobuf diagnostics. | ||
11 | func WarnsAndErrsToProto(warns []string, errs []error) (diags []*proto.Diagnostic) { | ||
12 | for _, w := range warns { | ||
13 | diags = AppendProtoDiag(diags, w) | ||
14 | } | ||
15 | |||
16 | for _, e := range errs { | ||
17 | diags = AppendProtoDiag(diags, e) | ||
18 | } | ||
19 | |||
20 | return diags | ||
21 | } | ||
22 | |||
23 | // AppendProtoDiag appends a new diagnostic from a warning string or an error. | ||
24 | // This panics if d is not a string or error. | ||
25 | func AppendProtoDiag(diags []*proto.Diagnostic, d interface{}) []*proto.Diagnostic { | ||
26 | switch d := d.(type) { | ||
27 | case cty.PathError: | ||
28 | ap := PathToAttributePath(d.Path) | ||
29 | diags = append(diags, &proto.Diagnostic{ | ||
30 | Severity: proto.Diagnostic_ERROR, | ||
31 | Summary: d.Error(), | ||
32 | Attribute: ap, | ||
33 | }) | ||
34 | case error: | ||
35 | diags = append(diags, &proto.Diagnostic{ | ||
36 | Severity: proto.Diagnostic_ERROR, | ||
37 | Summary: d.Error(), | ||
38 | }) | ||
39 | case string: | ||
40 | diags = append(diags, &proto.Diagnostic{ | ||
41 | Severity: proto.Diagnostic_WARNING, | ||
42 | Summary: d, | ||
43 | }) | ||
44 | case *proto.Diagnostic: | ||
45 | diags = append(diags, d) | ||
46 | case []*proto.Diagnostic: | ||
47 | diags = append(diags, d...) | ||
48 | } | ||
49 | return diags | ||
50 | } | ||
51 | |||
52 | // ProtoToDiagnostics converts a list of proto.Diagnostics to a tf.Diagnostics. | ||
53 | func ProtoToDiagnostics(ds []*proto.Diagnostic) tfdiags.Diagnostics { | ||
54 | var diags tfdiags.Diagnostics | ||
55 | for _, d := range ds { | ||
56 | var severity tfdiags.Severity | ||
57 | |||
58 | switch d.Severity { | ||
59 | case proto.Diagnostic_ERROR: | ||
60 | severity = tfdiags.Error | ||
61 | case proto.Diagnostic_WARNING: | ||
62 | severity = tfdiags.Warning | ||
63 | } | ||
64 | |||
65 | var newDiag tfdiags.Diagnostic | ||
66 | |||
67 | // if there's an attribute path, we need to create a AttributeValue diagnostic | ||
68 | if d.Attribute != nil { | ||
69 | path := AttributePathToPath(d.Attribute) | ||
70 | newDiag = tfdiags.AttributeValue(severity, d.Summary, d.Detail, path) | ||
71 | } else { | ||
72 | newDiag = tfdiags.WholeContainingBody(severity, d.Summary, d.Detail) | ||
73 | } | ||
74 | |||
75 | diags = diags.Append(newDiag) | ||
76 | } | ||
77 | |||
78 | return diags | ||
79 | } | ||
80 | |||
81 | // AttributePathToPath takes the proto encoded path and converts it to a cty.Path | ||
82 | func AttributePathToPath(ap *proto.AttributePath) cty.Path { | ||
83 | var p cty.Path | ||
84 | for _, step := range ap.Steps { | ||
85 | switch selector := step.Selector.(type) { | ||
86 | case *proto.AttributePath_Step_AttributeName: | ||
87 | p = p.GetAttr(selector.AttributeName) | ||
88 | case *proto.AttributePath_Step_ElementKeyString: | ||
89 | p = p.Index(cty.StringVal(selector.ElementKeyString)) | ||
90 | case *proto.AttributePath_Step_ElementKeyInt: | ||
91 | p = p.Index(cty.NumberIntVal(selector.ElementKeyInt)) | ||
92 | } | ||
93 | } | ||
94 | return p | ||
95 | } | ||
96 | |||
97 | // AttributePathToPath takes a cty.Path and converts it to a proto-encoded path. | ||
98 | func PathToAttributePath(p cty.Path) *proto.AttributePath { | ||
99 | ap := &proto.AttributePath{} | ||
100 | for _, step := range p { | ||
101 | switch selector := step.(type) { | ||
102 | case cty.GetAttrStep: | ||
103 | ap.Steps = append(ap.Steps, &proto.AttributePath_Step{ | ||
104 | Selector: &proto.AttributePath_Step_AttributeName{ | ||
105 | AttributeName: selector.Name, | ||
106 | }, | ||
107 | }) | ||
108 | case cty.IndexStep: | ||
109 | key := selector.Key | ||
110 | switch key.Type() { | ||
111 | case cty.String: | ||
112 | ap.Steps = append(ap.Steps, &proto.AttributePath_Step{ | ||
113 | Selector: &proto.AttributePath_Step_ElementKeyString{ | ||
114 | ElementKeyString: key.AsString(), | ||
115 | }, | ||
116 | }) | ||
117 | case cty.Number: | ||
118 | v, _ := key.AsBigFloat().Int64() | ||
119 | ap.Steps = append(ap.Steps, &proto.AttributePath_Step{ | ||
120 | Selector: &proto.AttributePath_Step_ElementKeyInt{ | ||
121 | ElementKeyInt: v, | ||
122 | }, | ||
123 | }) | ||
124 | default: | ||
125 | // We'll bail early if we encounter anything else, and just | ||
126 | // return the valid prefix. | ||
127 | return ap | ||
128 | } | ||
129 | } | ||
130 | } | ||
131 | return ap | ||
132 | } | ||