github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/command/jsonformat/computed/renderers/util.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package renderers 5 6 import ( 7 "fmt" 8 "strings" 9 10 "github.com/terramate-io/tf/command/format" 11 12 "github.com/hashicorp/hcl/v2/hclsyntax" 13 14 "github.com/terramate-io/tf/command/jsonformat/computed" 15 "github.com/terramate-io/tf/plans" 16 ) 17 18 // NoWarningsRenderer defines a Warnings function that returns an empty list of 19 // warnings. This can be used by other renderers to ensure we don't see lots of 20 // repeats of this empty function. 21 type NoWarningsRenderer struct{} 22 23 // WarningsHuman returns an empty slice, as the name NoWarningsRenderer suggests. 24 func (render NoWarningsRenderer) WarningsHuman(_ computed.Diff, _ int, _ computed.RenderHumanOpts) []string { 25 return nil 26 } 27 28 // nullSuffix returns the `-> null` suffix if the change is a delete action, and 29 // it has not been overridden. 30 func nullSuffix(action plans.Action, opts computed.RenderHumanOpts) string { 31 if !opts.OverrideNullSuffix && action == plans.Delete { 32 return opts.Colorize.Color(" [dark_gray]-> null[reset]") 33 } 34 return "" 35 } 36 37 // forcesReplacement returns the `# forces replacement` suffix if this change is 38 // driving the entire resource to be replaced. 39 func forcesReplacement(replace bool, opts computed.RenderHumanOpts) string { 40 if replace || opts.OverrideForcesReplacement { 41 return opts.Colorize.Color(" [red]# forces replacement[reset]") 42 } 43 return "" 44 } 45 46 // indent returns whitespace that is the required length for the specified 47 // indent. 48 func formatIndent(indent int) string { 49 return strings.Repeat(" ", indent) 50 } 51 52 // unchanged prints out a description saying how many of 'keyword' have been 53 // hidden because they are unchanged or noop actions. 54 func unchanged(keyword string, count int, opts computed.RenderHumanOpts) string { 55 if count == 1 { 56 return opts.Colorize.Color(fmt.Sprintf("[dark_gray]# (%d unchanged %s hidden)[reset]", count, keyword)) 57 } 58 return opts.Colorize.Color(fmt.Sprintf("[dark_gray]# (%d unchanged %ss hidden)[reset]", count, keyword)) 59 } 60 61 // EnsureValidAttributeName checks if `name` contains any HCL syntax and calls 62 // and returns hclEscapeString. 63 func EnsureValidAttributeName(name string) string { 64 if !hclsyntax.ValidIdentifier(name) { 65 return hclEscapeString(name) 66 } 67 return name 68 } 69 70 // hclEscapeString formats the input string into a format that is safe for 71 // rendering within HCL. 72 // 73 // Note, this function doesn't actually do a very good job of this currently. We 74 // need to expose some internal functions from HCL in a future version and call 75 // them from here. For now, just use "%q" formatting. 76 func hclEscapeString(str string) string { 77 // TODO: Replace this with more complete HCL logic instead of the simple 78 // go workaround. 79 return fmt.Sprintf("%q", str) 80 } 81 82 // writeDiffActionSymbol writes out the symbols for the associated action, and 83 // handles localized colorization of the symbol as well as indenting the symbol 84 // to be 4 spaces wide. 85 // 86 // If the opts has HideDiffActionSymbols set then this function returns an empty 87 // string. 88 func writeDiffActionSymbol(action plans.Action, opts computed.RenderHumanOpts) string { 89 if opts.HideDiffActionSymbols { 90 return "" 91 } 92 return fmt.Sprintf("%s ", opts.Colorize.Color(format.DiffActionSymbol(action))) 93 }