96 lines
2.3 KiB
Go
96 lines
2.3 KiB
Go
|
package repl
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/hashicorp/terraform/config"
|
||
|
"github.com/hashicorp/terraform/terraform"
|
||
|
)
|
||
|
|
||
|
// 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 {
|
||
|
// Interpolater is used for calculating interpolations
|
||
|
Interpolater *terraform.Interpolater
|
||
|
}
|
||
|
|
||
|
// 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, error) {
|
||
|
switch {
|
||
|
case strings.TrimSpace(line) == "exit":
|
||
|
return "", ErrSessionExit
|
||
|
case strings.TrimSpace(line) == "help":
|
||
|
return s.handleHelp()
|
||
|
default:
|
||
|
return s.handleEval(line)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (s *Session) handleEval(line string) (string, error) {
|
||
|
// Wrap the line to make it an interpolation.
|
||
|
line = fmt.Sprintf("${%s}", line)
|
||
|
|
||
|
// Parse the line
|
||
|
raw, err := config.NewRawConfig(map[string]interface{}{
|
||
|
"value": line,
|
||
|
})
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
// Set the value
|
||
|
raw.Key = "value"
|
||
|
|
||
|
// Get the values
|
||
|
vars, err := s.Interpolater.Values(&terraform.InterpolationScope{
|
||
|
Path: []string{"root"},
|
||
|
}, raw.Variables)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
// Interpolate
|
||
|
if err := raw.Interpolate(vars); err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
// If we have any unknown keys, let the user know.
|
||
|
if ks := raw.UnknownKeys(); len(ks) > 0 {
|
||
|
return "", fmt.Errorf("unknown values referenced, can't compute value")
|
||
|
}
|
||
|
|
||
|
// Read the value
|
||
|
result, err := FormatResult(raw.Value())
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
return result, nil
|
||
|
}
|
||
|
|
||
|
func (s *Session) handleHelp() (string, error) {
|
||
|
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
|
||
|
}
|