github.com/gavinw2006/hashicorp-terraform@v0.11.12-beta1/repl/session.go (about)

     1  package repl
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"github.com/hashicorp/terraform/config"
     9  	"github.com/hashicorp/terraform/terraform"
    10  )
    11  
    12  // ErrSessionExit is a special error result that should be checked for
    13  // from Handle to signal a graceful exit.
    14  var ErrSessionExit = errors.New("session exit")
    15  
    16  // Session represents the state for a single REPL session.
    17  type Session struct {
    18  	// Interpolater is used for calculating interpolations
    19  	Interpolater *terraform.Interpolater
    20  }
    21  
    22  // Handle handles a single line of input from the REPL.
    23  //
    24  // This is a stateful operation if a command is given (such as setting
    25  // a variable). This function should not be called in parallel.
    26  //
    27  // The return value is the output and the error to show.
    28  func (s *Session) Handle(line string) (string, error) {
    29  	switch {
    30  	case strings.TrimSpace(line) == "exit":
    31  		return "", ErrSessionExit
    32  	case strings.TrimSpace(line) == "help":
    33  		return s.handleHelp()
    34  	default:
    35  		return s.handleEval(line)
    36  	}
    37  }
    38  
    39  func (s *Session) handleEval(line string) (string, error) {
    40  	// Wrap the line to make it an interpolation.
    41  	line = fmt.Sprintf("${%s}", line)
    42  
    43  	// Parse the line
    44  	raw, err := config.NewRawConfig(map[string]interface{}{
    45  		"value": line,
    46  	})
    47  	if err != nil {
    48  		return "", err
    49  	}
    50  
    51  	// Set the value
    52  	raw.Key = "value"
    53  
    54  	// Get the values
    55  	vars, err := s.Interpolater.Values(&terraform.InterpolationScope{
    56  		Path: []string{"root"},
    57  	}, raw.Variables)
    58  	if err != nil {
    59  		return "", err
    60  	}
    61  
    62  	// Interpolate
    63  	if err := raw.Interpolate(vars); err != nil {
    64  		return "", err
    65  	}
    66  
    67  	// If we have any unknown keys, let the user know.
    68  	if ks := raw.UnknownKeys(); len(ks) > 0 {
    69  		return "", fmt.Errorf("unknown values referenced, can't compute value")
    70  	}
    71  
    72  	// Read the value
    73  	result, err := FormatResult(raw.Value())
    74  	if err != nil {
    75  		return "", err
    76  	}
    77  
    78  	return result, nil
    79  }
    80  
    81  func (s *Session) handleHelp() (string, error) {
    82  	text := `
    83  The Terraform console allows you to experiment with Terraform interpolations.
    84  You may access resources in the state (if you have one) just as you would
    85  from a configuration. For example: "aws_instance.foo.id" would evaluate
    86  to the ID of "aws_instance.foo" if it exists in your state.
    87  
    88  Type in the interpolation to test and hit <enter> to see the result.
    89  
    90  To exit the console, type "exit" and hit <enter>, or use Control-C or
    91  Control-D.
    92  `
    93  
    94  	return strings.TrimSpace(text), nil
    95  }