github.com/greysond/terraform@v0.8.5-0.20170124173113-439b5507bbe9/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 }