mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-30 10:47:14 -06:00
8b2b569d6e
Use a slightly modified value renderer from terraform-provider-testing to display values in the console REPL, as well as outputs from the apply and outputs subcommands. Derived from code in this repository, MIT licensed: https://github.com/apparentlymart/terraform-provider-testing Note that this is technically a breaking change for the console subcommand, which would previously error if the user attempted to render an unknown value (such as an unset variable). This was marked as an unintentional side effect, with the goal being the new behaviour of rendering "(unknown)", which is why I changed the behaviour in this commit.
80 lines
2.2 KiB
Go
80 lines
2.2 KiB
Go
package repl
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
|
|
"github.com/zclconf/go-cty/cty"
|
|
|
|
"github.com/hashicorp/hcl/v2"
|
|
"github.com/hashicorp/hcl/v2/hclsyntax"
|
|
"github.com/hashicorp/terraform/lang"
|
|
"github.com/hashicorp/terraform/tfdiags"
|
|
)
|
|
|
|
// ErrSessionExit is a special error result that should be checked for
|
|
// from Handle to signal a graceful exit.
|
|
var ErrSessionExit = errors.New("session exit")
|
|
|
|
// Session represents the state for a single REPL session.
|
|
type Session struct {
|
|
// Scope is the evaluation scope where expressions will be evaluated.
|
|
Scope *lang.Scope
|
|
}
|
|
|
|
// Handle handles a single line of input from the REPL.
|
|
//
|
|
// This is a stateful operation if a command is given (such as setting
|
|
// a variable). This function should not be called in parallel.
|
|
//
|
|
// The return value is the output and the error to show.
|
|
func (s *Session) Handle(line string) (string, bool, tfdiags.Diagnostics) {
|
|
switch {
|
|
case strings.TrimSpace(line) == "":
|
|
return "", false, nil
|
|
case strings.TrimSpace(line) == "exit":
|
|
return "", true, nil
|
|
case strings.TrimSpace(line) == "help":
|
|
ret, diags := s.handleHelp()
|
|
return ret, false, diags
|
|
default:
|
|
ret, diags := s.handleEval(line)
|
|
return ret, false, diags
|
|
}
|
|
}
|
|
|
|
func (s *Session) handleEval(line string) (string, tfdiags.Diagnostics) {
|
|
var diags tfdiags.Diagnostics
|
|
|
|
// Parse the given line as an expression
|
|
expr, parseDiags := hclsyntax.ParseExpression([]byte(line), "<console-input>", hcl.Pos{Line: 1, Column: 1})
|
|
diags = diags.Append(parseDiags)
|
|
if parseDiags.HasErrors() {
|
|
return "", diags
|
|
}
|
|
|
|
val, valDiags := s.Scope.EvalExpr(expr, cty.DynamicPseudoType)
|
|
diags = diags.Append(valDiags)
|
|
if valDiags.HasErrors() {
|
|
return "", diags
|
|
}
|
|
|
|
return FormatValue(val, 0), diags
|
|
}
|
|
|
|
func (s *Session) handleHelp() (string, tfdiags.Diagnostics) {
|
|
text := `
|
|
The Terraform console allows you to experiment with Terraform interpolations.
|
|
You may access resources in the state (if you have one) just as you would
|
|
from a configuration. For example: "aws_instance.foo.id" would evaluate
|
|
to the ID of "aws_instance.foo" if it exists in your state.
|
|
|
|
Type in the interpolation to test and hit <enter> to see the result.
|
|
|
|
To exit the console, type "exit" and hit <enter>, or use Control-C or
|
|
Control-D.
|
|
`
|
|
|
|
return strings.TrimSpace(text), nil
|
|
}
|