github.com/jaredpalmer/terraform@v1.1.0-alpha20210908.0.20210911170307-88705c943a03/internal/repl/session.go (about)

     1  package repl
     2  
     3  import (
     4  	"strings"
     5  
     6  	"github.com/zclconf/go-cty/cty"
     7  
     8  	"github.com/hashicorp/hcl/v2"
     9  	"github.com/hashicorp/hcl/v2/hclsyntax"
    10  	"github.com/hashicorp/terraform/internal/lang"
    11  	"github.com/hashicorp/terraform/internal/tfdiags"
    12  )
    13  
    14  // Session represents the state for a single REPL session.
    15  type Session struct {
    16  	// Scope is the evaluation scope where expressions will be evaluated.
    17  	Scope *lang.Scope
    18  }
    19  
    20  // Handle handles a single line of input from the REPL.
    21  //
    22  // This is a stateful operation if a command is given (such as setting
    23  // a variable). This function should not be called in parallel.
    24  //
    25  // The return value is the output and the error to show.
    26  func (s *Session) Handle(line string) (string, bool, tfdiags.Diagnostics) {
    27  	switch {
    28  	case strings.TrimSpace(line) == "":
    29  		return "", false, nil
    30  	case strings.TrimSpace(line) == "exit":
    31  		return "", true, nil
    32  	case strings.TrimSpace(line) == "help":
    33  		ret, diags := s.handleHelp()
    34  		return ret, false, diags
    35  	default:
    36  		ret, diags := s.handleEval(line)
    37  		return ret, false, diags
    38  	}
    39  }
    40  
    41  func (s *Session) handleEval(line string) (string, tfdiags.Diagnostics) {
    42  	var diags tfdiags.Diagnostics
    43  
    44  	// Parse the given line as an expression
    45  	expr, parseDiags := hclsyntax.ParseExpression([]byte(line), "<console-input>", hcl.Pos{Line: 1, Column: 1})
    46  	diags = diags.Append(parseDiags)
    47  	if parseDiags.HasErrors() {
    48  		return "", diags
    49  	}
    50  
    51  	val, valDiags := s.Scope.EvalExpr(expr, cty.DynamicPseudoType)
    52  	diags = diags.Append(valDiags)
    53  	if valDiags.HasErrors() {
    54  		return "", diags
    55  	}
    56  
    57  	return FormatValue(val, 0), diags
    58  }
    59  
    60  func (s *Session) handleHelp() (string, tfdiags.Diagnostics) {
    61  	text := `
    62  The Terraform console allows you to experiment with Terraform interpolations.
    63  You may access resources in the state (if you have one) just as you would
    64  from a configuration. For example: "aws_instance.foo.id" would evaluate
    65  to the ID of "aws_instance.foo" if it exists in your state.
    66  
    67  Type in the interpolation to test and hit <enter> to see the result.
    68  
    69  To exit the console, type "exit" and hit <enter>, or use Control-C or
    70  Control-D.
    71  `
    72  
    73  	return strings.TrimSpace(text), nil
    74  }