package repl import ( "strings" "github.com/zclconf/go-cty/cty" "github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2/hclsyntax" "github.com/hashicorp/terraform/internal/tfdiags" "github.com/hashicorp/terraform/lang" ) // 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), "", 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 to see the result. To exit the console, type "exit" and hit , or use Control-C or Control-D. ` return strings.TrimSpace(text), nil }