mirror of
https://github.com/opentofu/opentofu.git
synced 2025-01-02 04:07:22 -06:00
b40a4fb741
This is part of a general effort to move all of Terraform's non-library package surface under internal in order to reinforce that these are for internal use within Terraform only. If you were previously importing packages under this prefix into an external codebase, you could pin to an earlier release tag as an interim solution until you've make a plan to achieve the same functionality some other way.
133 lines
3.6 KiB
Go
133 lines
3.6 KiB
Go
package convert
|
|
|
|
import (
|
|
"github.com/hashicorp/terraform/internal/tfdiags"
|
|
proto "github.com/hashicorp/terraform/internal/tfplugin5"
|
|
"github.com/zclconf/go-cty/cty"
|
|
)
|
|
|
|
// WarnsAndErrorsToProto converts the warnings and errors return by the legacy
|
|
// provider to protobuf diagnostics.
|
|
func WarnsAndErrsToProto(warns []string, errs []error) (diags []*proto.Diagnostic) {
|
|
for _, w := range warns {
|
|
diags = AppendProtoDiag(diags, w)
|
|
}
|
|
|
|
for _, e := range errs {
|
|
diags = AppendProtoDiag(diags, e)
|
|
}
|
|
|
|
return diags
|
|
}
|
|
|
|
// AppendProtoDiag appends a new diagnostic from a warning string or an error.
|
|
// This panics if d is not a string or error.
|
|
func AppendProtoDiag(diags []*proto.Diagnostic, d interface{}) []*proto.Diagnostic {
|
|
switch d := d.(type) {
|
|
case cty.PathError:
|
|
ap := PathToAttributePath(d.Path)
|
|
diags = append(diags, &proto.Diagnostic{
|
|
Severity: proto.Diagnostic_ERROR,
|
|
Summary: d.Error(),
|
|
Attribute: ap,
|
|
})
|
|
case error:
|
|
diags = append(diags, &proto.Diagnostic{
|
|
Severity: proto.Diagnostic_ERROR,
|
|
Summary: d.Error(),
|
|
})
|
|
case string:
|
|
diags = append(diags, &proto.Diagnostic{
|
|
Severity: proto.Diagnostic_WARNING,
|
|
Summary: d,
|
|
})
|
|
case *proto.Diagnostic:
|
|
diags = append(diags, d)
|
|
case []*proto.Diagnostic:
|
|
diags = append(diags, d...)
|
|
}
|
|
return diags
|
|
}
|
|
|
|
// ProtoToDiagnostics converts a list of proto.Diagnostics to a tf.Diagnostics.
|
|
func ProtoToDiagnostics(ds []*proto.Diagnostic) tfdiags.Diagnostics {
|
|
var diags tfdiags.Diagnostics
|
|
for _, d := range ds {
|
|
var severity tfdiags.Severity
|
|
|
|
switch d.Severity {
|
|
case proto.Diagnostic_ERROR:
|
|
severity = tfdiags.Error
|
|
case proto.Diagnostic_WARNING:
|
|
severity = tfdiags.Warning
|
|
}
|
|
|
|
var newDiag tfdiags.Diagnostic
|
|
|
|
// if there's an attribute path, we need to create a AttributeValue diagnostic
|
|
if d.Attribute != nil && len(d.Attribute.Steps) > 0 {
|
|
path := AttributePathToPath(d.Attribute)
|
|
newDiag = tfdiags.AttributeValue(severity, d.Summary, d.Detail, path)
|
|
} else {
|
|
newDiag = tfdiags.WholeContainingBody(severity, d.Summary, d.Detail)
|
|
}
|
|
|
|
diags = diags.Append(newDiag)
|
|
}
|
|
|
|
return diags
|
|
}
|
|
|
|
// AttributePathToPath takes the proto encoded path and converts it to a cty.Path
|
|
func AttributePathToPath(ap *proto.AttributePath) cty.Path {
|
|
var p cty.Path
|
|
for _, step := range ap.Steps {
|
|
switch selector := step.Selector.(type) {
|
|
case *proto.AttributePath_Step_AttributeName:
|
|
p = p.GetAttr(selector.AttributeName)
|
|
case *proto.AttributePath_Step_ElementKeyString:
|
|
p = p.Index(cty.StringVal(selector.ElementKeyString))
|
|
case *proto.AttributePath_Step_ElementKeyInt:
|
|
p = p.Index(cty.NumberIntVal(selector.ElementKeyInt))
|
|
}
|
|
}
|
|
return p
|
|
}
|
|
|
|
// AttributePathToPath takes a cty.Path and converts it to a proto-encoded path.
|
|
func PathToAttributePath(p cty.Path) *proto.AttributePath {
|
|
ap := &proto.AttributePath{}
|
|
for _, step := range p {
|
|
switch selector := step.(type) {
|
|
case cty.GetAttrStep:
|
|
ap.Steps = append(ap.Steps, &proto.AttributePath_Step{
|
|
Selector: &proto.AttributePath_Step_AttributeName{
|
|
AttributeName: selector.Name,
|
|
},
|
|
})
|
|
case cty.IndexStep:
|
|
key := selector.Key
|
|
switch key.Type() {
|
|
case cty.String:
|
|
ap.Steps = append(ap.Steps, &proto.AttributePath_Step{
|
|
Selector: &proto.AttributePath_Step_ElementKeyString{
|
|
ElementKeyString: key.AsString(),
|
|
},
|
|
})
|
|
case cty.Number:
|
|
v, _ := key.AsBigFloat().Int64()
|
|
ap.Steps = append(ap.Steps, &proto.AttributePath_Step{
|
|
Selector: &proto.AttributePath_Step_ElementKeyInt{
|
|
ElementKeyInt: v,
|
|
},
|
|
})
|
|
default:
|
|
// We'll bail early if we encounter anything else, and just
|
|
// return the valid prefix.
|
|
return ap
|
|
}
|
|
}
|
|
}
|
|
return ap
|
|
}
|