github.com/hashicorp/terraform-plugin-sdk@v1.17.2/internal/tfdiags/config_traversals.go (about) 1 package tfdiags 2 3 import ( 4 "bytes" 5 "fmt" 6 "strconv" 7 8 "github.com/zclconf/go-cty/cty" 9 ) 10 11 // FormatCtyPath is a helper function to produce a user-friendly string 12 // representation of a cty.Path. The result uses a syntax similar to the 13 // HCL expression language in the hope of it being familiar to users. 14 func FormatCtyPath(path cty.Path) string { 15 var buf bytes.Buffer 16 for _, step := range path { 17 switch ts := step.(type) { 18 case cty.GetAttrStep: 19 fmt.Fprintf(&buf, ".%s", ts.Name) 20 case cty.IndexStep: 21 buf.WriteByte('[') 22 key := ts.Key 23 keyTy := key.Type() 24 switch { 25 case key.IsNull(): 26 buf.WriteString("null") 27 case !key.IsKnown(): 28 buf.WriteString("(not yet known)") 29 case keyTy == cty.Number: 30 bf := key.AsBigFloat() 31 buf.WriteString(bf.Text('g', -1)) 32 case keyTy == cty.String: 33 buf.WriteString(strconv.Quote(key.AsString())) 34 default: 35 buf.WriteString("...") 36 } 37 buf.WriteByte(']') 38 } 39 } 40 return buf.String() 41 } 42 43 // FormatError is a helper function to produce a user-friendly string 44 // representation of certain special error types that we might want to 45 // include in diagnostic messages. 46 // 47 // This currently has special behavior only for cty.PathError, where a 48 // non-empty path is rendered in a HCL-like syntax as context. 49 func FormatError(err error) string { 50 perr, ok := err.(cty.PathError) 51 if !ok || len(perr.Path) == 0 { 52 return err.Error() 53 } 54 55 return fmt.Sprintf("%s: %s", FormatCtyPath(perr.Path), perr.Error()) 56 } 57 58 // FormatErrorPrefixed is like FormatError except that it presents any path 59 // information after the given prefix string, which is assumed to contain 60 // an HCL syntax representation of the value that errors are relative to. 61 func FormatErrorPrefixed(err error, prefix string) string { 62 perr, ok := err.(cty.PathError) 63 if !ok || len(perr.Path) == 0 { 64 return fmt.Sprintf("%s: %s", prefix, err.Error()) 65 } 66 67 return fmt.Sprintf("%s%s: %s", prefix, FormatCtyPath(perr.Path), perr.Error()) 68 }