github.com/rhenning/terraform@v0.8.0-beta2/command/console.go (about)

     1  package command
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"os"
     7  	"strings"
     8  
     9  	"github.com/hashicorp/terraform/helper/wrappedstreams"
    10  	"github.com/hashicorp/terraform/repl"
    11  
    12  	"github.com/mitchellh/cli"
    13  )
    14  
    15  // ConsoleCommand is a Command implementation that applies a Terraform
    16  // configuration and actually builds or changes infrastructure.
    17  type ConsoleCommand struct {
    18  	Meta
    19  
    20  	// When this channel is closed, the apply will be cancelled.
    21  	ShutdownCh <-chan struct{}
    22  }
    23  
    24  func (c *ConsoleCommand) Run(args []string) int {
    25  	args = c.Meta.process(args, true)
    26  	cmdFlags := c.Meta.flagSet("console")
    27  	cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path")
    28  	cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
    29  	if err := cmdFlags.Parse(args); err != nil {
    30  		return 1
    31  	}
    32  
    33  	pwd, err := os.Getwd()
    34  	if err != nil {
    35  		c.Ui.Error(fmt.Sprintf("Error getting pwd: %s", err))
    36  		return 1
    37  	}
    38  
    39  	var configPath string
    40  	args = cmdFlags.Args()
    41  	if len(args) > 1 {
    42  		c.Ui.Error("The console command expects at most one argument.")
    43  		cmdFlags.Usage()
    44  		return 1
    45  	} else if len(args) == 1 {
    46  		configPath = args[0]
    47  	} else {
    48  		configPath = pwd
    49  	}
    50  
    51  	// Build the context based on the arguments given
    52  	ctx, _, err := c.Context(contextOpts{
    53  		Path:        configPath,
    54  		PathEmptyOk: true,
    55  		StatePath:   c.Meta.statePath,
    56  	})
    57  	if err != nil {
    58  		c.Ui.Error(err.Error())
    59  		return 1
    60  	}
    61  
    62  	// Setup the UI so we can output directly to stdout
    63  	ui := &cli.BasicUi{
    64  		Writer:      wrappedstreams.Stdout(),
    65  		ErrorWriter: wrappedstreams.Stderr(),
    66  	}
    67  
    68  	// IO Loop
    69  	session := &repl.Session{
    70  		Interpolater: ctx.Interpolater(),
    71  	}
    72  
    73  	// Determine if stdin is a pipe. If so, we evaluate directly.
    74  	if c.StdinPiped() {
    75  		return c.modePiped(session, ui)
    76  	}
    77  
    78  	return c.modeInteractive(session, ui)
    79  }
    80  
    81  func (c *ConsoleCommand) modePiped(session *repl.Session, ui cli.Ui) int {
    82  	var lastResult string
    83  	scanner := bufio.NewScanner(wrappedstreams.Stdin())
    84  	for scanner.Scan() {
    85  		// Handle it. If there is an error exit immediately
    86  		result, err := session.Handle(strings.TrimSpace(scanner.Text()))
    87  		if err != nil {
    88  			ui.Error(err.Error())
    89  			return 1
    90  		}
    91  
    92  		// Store the last result
    93  		lastResult = result
    94  	}
    95  
    96  	// Output the final result
    97  	ui.Output(lastResult)
    98  
    99  	return 0
   100  }
   101  
   102  func (c *ConsoleCommand) Help() string {
   103  	helpText := `
   104  Usage: terraform console [options] [DIR]
   105  
   106    Starts an interactive console for experimenting with Terraform
   107    interpolations.
   108  
   109    This will open an interactive console that you can use to type
   110    interpolations into and inspect their values. This command loads the
   111    current state. This lets you explore and test interpolations before
   112    using them in future configurations.
   113  
   114    This command will never modify your state.
   115  
   116    DIR can be set to a directory with a Terraform state to load. By
   117    default, this will default to the current working directory.
   118  
   119  Options:
   120  
   121    -state=path            Path to read state. Defaults to "terraform.tfstate"
   122  
   123    -var 'foo=bar'         Set a variable in the Terraform configuration. This
   124                           flag can be set multiple times.
   125  
   126    -var-file=foo          Set variables in the Terraform configuration from
   127                           a file. If "terraform.tfvars" is present, it will be
   128                           automatically loaded if this flag is not specified.
   129  
   130  
   131  `
   132  	return strings.TrimSpace(helpText)
   133  }
   134  
   135  func (c *ConsoleCommand) Synopsis() string {
   136  	return "Interactive console for Terraform interpolations"
   137  }