mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-26 00:41:27 -06:00
39e609d5fd
Previously we were using the experimental HCL 2 repository, but now we'll shift over to the v2 import path within the main HCL repository as part of actually releasing HCL 2.0 as stable. This is a mechanical search/replace to the new import paths. It also switches to the v2.0.0 release of HCL, which includes some new code that Terraform didn't previously have but should not change any behavior that matters for Terraform's purposes. For the moment the experimental HCL2 repository is still an indirect dependency via terraform-config-inspect, so it remains in our go.sum and vendor directories for the moment. Because terraform-config-inspect uses a much smaller subset of the HCL2 functionality, this does still manage to prune the vendor directory a little. A subsequent release of terraform-config-inspect should allow us to completely remove that old repository in a future commit.
100 lines
3.0 KiB
Go
100 lines
3.0 KiB
Go
package repl
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/zclconf/go-cty/cty"
|
|
|
|
"github.com/hashicorp/hcl/v2"
|
|
"github.com/hashicorp/hcl/v2/hclsyntax"
|
|
"github.com/hashicorp/terraform/configs/hcl2shim"
|
|
"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
|
|
}
|
|
|
|
if !val.IsWhollyKnown() {
|
|
// FIXME: In future, once we've updated the result formatter to be
|
|
// cty-aware, we should just include unknown values as "(not yet known)"
|
|
// in the serialized result, allowing the rest (if any) to be seen.
|
|
diags = diags.Append(fmt.Errorf("Result depends on values that cannot be determined until after \"terraform apply\"."))
|
|
return "", diags
|
|
}
|
|
|
|
// Our formatter still wants an old-style raw interface{} value, so
|
|
// for now we'll just shim it.
|
|
// FIXME: Port the formatter to work with cty.Value directly.
|
|
legacyVal := hcl2shim.ConfigValueFromHCL2(val)
|
|
result, err := FormatResult(legacyVal)
|
|
if err != nil {
|
|
diags = diags.Append(err)
|
|
return "", diags
|
|
}
|
|
|
|
return result, 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
|
|
}
|