mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-30 10:47:14 -06:00
f085af4ba6
This now uses the HCL2 parser and evaluator APIs and evaluates in terms of a new-style *lang.Scope, rather than the old terraform.Interpolator type that is no longer functional. The Context.Eval method used here behaves differently than the Context.Interpolater method used previously: it performs a graph walk to populate transient values such as input variables, local values, and output values, and produces its scope in terms of the result of that graph walk. Because of this, it is a lot more robust than the prior method when asked to resolve references other than those that are persisted in the state.
117 lines
2.3 KiB
Go
117 lines
2.3 KiB
Go
package repl
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"fmt"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// FormatResult formats the given result value for human-readable output.
|
|
//
|
|
// The value must currently be a string, list, map, and any nested values
|
|
// with those same types.
|
|
func FormatResult(value interface{}) (string, error) {
|
|
return formatResult(value, false)
|
|
}
|
|
|
|
func formatResult(value interface{}, nested bool) (string, error) {
|
|
if value == nil {
|
|
return "null", nil
|
|
}
|
|
switch output := value.(type) {
|
|
case string:
|
|
if nested {
|
|
return fmt.Sprintf("%q", output), nil
|
|
}
|
|
return output, nil
|
|
case int:
|
|
return strconv.Itoa(output), nil
|
|
case float64:
|
|
return fmt.Sprintf("%g", output), nil
|
|
case bool:
|
|
switch {
|
|
case output == true:
|
|
return "true", nil
|
|
default:
|
|
return "false", nil
|
|
}
|
|
case []interface{}:
|
|
return formatListResult(output)
|
|
case map[string]interface{}:
|
|
return formatMapResult(output)
|
|
default:
|
|
return "", fmt.Errorf("unknown value type: %T", value)
|
|
}
|
|
}
|
|
|
|
func formatListResult(value []interface{}) (string, error) {
|
|
var outputBuf bytes.Buffer
|
|
outputBuf.WriteString("[")
|
|
if len(value) > 0 {
|
|
outputBuf.WriteString("\n")
|
|
}
|
|
|
|
for _, v := range value {
|
|
raw, err := formatResult(v, true)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
outputBuf.WriteString(indent(raw))
|
|
outputBuf.WriteString(",\n")
|
|
}
|
|
|
|
outputBuf.WriteString("]")
|
|
return outputBuf.String(), nil
|
|
}
|
|
|
|
func formatMapResult(value map[string]interface{}) (string, error) {
|
|
ks := make([]string, 0, len(value))
|
|
for k, _ := range value {
|
|
ks = append(ks, k)
|
|
}
|
|
sort.Strings(ks)
|
|
|
|
var outputBuf bytes.Buffer
|
|
outputBuf.WriteString("{")
|
|
if len(value) > 0 {
|
|
outputBuf.WriteString("\n")
|
|
}
|
|
|
|
for _, k := range ks {
|
|
v := value[k]
|
|
rawK, err := formatResult(k, true)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
rawV, err := formatResult(v, true)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
outputBuf.WriteString(indent(fmt.Sprintf("%s = %s", rawK, rawV)))
|
|
outputBuf.WriteString("\n")
|
|
}
|
|
|
|
outputBuf.WriteString("}")
|
|
return outputBuf.String(), nil
|
|
}
|
|
|
|
func indent(value string) string {
|
|
var outputBuf bytes.Buffer
|
|
s := bufio.NewScanner(strings.NewReader(value))
|
|
newline := false
|
|
for s.Scan() {
|
|
if newline {
|
|
outputBuf.WriteByte('\n')
|
|
}
|
|
outputBuf.WriteString(" " + s.Text())
|
|
newline = true
|
|
}
|
|
|
|
return outputBuf.String()
|
|
}
|