github.com/rvichery/terraform@v0.11.10/command/console.go (about) 1 package command 2 3 import ( 4 "bufio" 5 "fmt" 6 "strings" 7 8 "github.com/hashicorp/terraform/backend" 9 "github.com/hashicorp/terraform/config" 10 "github.com/hashicorp/terraform/helper/wrappedstreams" 11 "github.com/hashicorp/terraform/repl" 12 "github.com/hashicorp/terraform/tfdiags" 13 14 "github.com/mitchellh/cli" 15 ) 16 17 // ConsoleCommand is a Command implementation that applies a Terraform 18 // configuration and actually builds or changes infrastructure. 19 type ConsoleCommand struct { 20 Meta 21 } 22 23 func (c *ConsoleCommand) Run(args []string) int { 24 args, err := c.Meta.process(args, true) 25 if err != nil { 26 return 1 27 } 28 29 cmdFlags := c.Meta.flagSet("console") 30 cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path") 31 cmdFlags.Usage = func() { c.Ui.Error(c.Help()) } 32 if err := cmdFlags.Parse(args); err != nil { 33 return 1 34 } 35 36 configPath, err := ModulePath(cmdFlags.Args()) 37 if err != nil { 38 c.Ui.Error(err.Error()) 39 return 1 40 } 41 42 var diags tfdiags.Diagnostics 43 44 // Load the module 45 mod, diags := c.Module(configPath) 46 if diags.HasErrors() { 47 c.showDiagnostics(diags) 48 return 1 49 } 50 51 var conf *config.Config 52 if mod != nil { 53 conf = mod.Config() 54 } 55 56 // Load the backend 57 b, err := c.Backend(&BackendOpts{ 58 Config: conf, 59 }) 60 61 if err != nil { 62 c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err)) 63 return 1 64 } 65 66 // We require a local backend 67 local, ok := b.(backend.Local) 68 if !ok { 69 c.Ui.Error(ErrUnsupportedLocalOp) 70 return 1 71 } 72 73 // Build the operation 74 opReq := c.Operation() 75 opReq.Module = mod 76 77 // Get the context 78 ctx, _, err := local.Context(opReq) 79 if err != nil { 80 c.Ui.Error(err.Error()) 81 return 1 82 } 83 84 defer func() { 85 err := opReq.StateLocker.Unlock(nil) 86 if err != nil { 87 c.Ui.Error(err.Error()) 88 } 89 }() 90 91 // Setup the UI so we can output directly to stdout 92 ui := &cli.BasicUi{ 93 Writer: wrappedstreams.Stdout(), 94 ErrorWriter: wrappedstreams.Stderr(), 95 } 96 97 // IO Loop 98 session := &repl.Session{ 99 Interpolater: ctx.Interpolater(), 100 } 101 102 // Determine if stdin is a pipe. If so, we evaluate directly. 103 if c.StdinPiped() { 104 return c.modePiped(session, ui) 105 } 106 107 return c.modeInteractive(session, ui) 108 } 109 110 func (c *ConsoleCommand) modePiped(session *repl.Session, ui cli.Ui) int { 111 var lastResult string 112 scanner := bufio.NewScanner(wrappedstreams.Stdin()) 113 for scanner.Scan() { 114 // Handle it. If there is an error exit immediately 115 result, err := session.Handle(strings.TrimSpace(scanner.Text())) 116 if err != nil { 117 ui.Error(err.Error()) 118 return 1 119 } 120 121 // Store the last result 122 lastResult = result 123 } 124 125 // Output the final result 126 ui.Output(lastResult) 127 128 return 0 129 } 130 131 func (c *ConsoleCommand) Help() string { 132 helpText := ` 133 Usage: terraform console [options] [DIR] 134 135 Starts an interactive console for experimenting with Terraform 136 interpolations. 137 138 This will open an interactive console that you can use to type 139 interpolations into and inspect their values. This command loads the 140 current state. This lets you explore and test interpolations before 141 using them in future configurations. 142 143 This command will never modify your state. 144 145 DIR can be set to a directory with a Terraform state to load. By 146 default, this will default to the current working directory. 147 148 Options: 149 150 -state=path Path to read state. Defaults to "terraform.tfstate" 151 152 -var 'foo=bar' Set a variable in the Terraform configuration. This 153 flag can be set multiple times. 154 155 -var-file=foo Set variables in the Terraform configuration from 156 a file. If "terraform.tfvars" or any ".auto.tfvars" 157 files are present, they will be automatically loaded. 158 159 160 ` 161 return strings.TrimSpace(helpText) 162 } 163 164 func (c *ConsoleCommand) Synopsis() string { 165 return "Interactive console for Terraform interpolations" 166 }