mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
The state locking improvements for the regular command had the side effect of locking the state in the console, import, graph and push commands. Those commands had been updated to get a state via the Backend.Context method, which locks the state whenever possible, and now need to call Unlock directly. Add Unlock calls to all commands that call Context directly.
167 lines
3.7 KiB
Go
167 lines
3.7 KiB
Go
package command
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/hashicorp/terraform/backend"
|
|
"github.com/hashicorp/terraform/config"
|
|
"github.com/hashicorp/terraform/helper/wrappedstreams"
|
|
"github.com/hashicorp/terraform/repl"
|
|
"github.com/hashicorp/terraform/tfdiags"
|
|
|
|
"github.com/mitchellh/cli"
|
|
)
|
|
|
|
// ConsoleCommand is a Command implementation that applies a Terraform
|
|
// configuration and actually builds or changes infrastructure.
|
|
type ConsoleCommand struct {
|
|
Meta
|
|
}
|
|
|
|
func (c *ConsoleCommand) Run(args []string) int {
|
|
args, err := c.Meta.process(args, true)
|
|
if err != nil {
|
|
return 1
|
|
}
|
|
|
|
cmdFlags := c.Meta.flagSet("console")
|
|
cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path")
|
|
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
|
if err := cmdFlags.Parse(args); err != nil {
|
|
return 1
|
|
}
|
|
|
|
configPath, err := ModulePath(cmdFlags.Args())
|
|
if err != nil {
|
|
c.Ui.Error(err.Error())
|
|
return 1
|
|
}
|
|
|
|
var diags tfdiags.Diagnostics
|
|
|
|
// Load the module
|
|
mod, diags := c.Module(configPath)
|
|
if diags.HasErrors() {
|
|
c.showDiagnostics(diags)
|
|
return 1
|
|
}
|
|
|
|
var conf *config.Config
|
|
if mod != nil {
|
|
conf = mod.Config()
|
|
}
|
|
|
|
// Load the backend
|
|
b, err := c.Backend(&BackendOpts{
|
|
Config: conf,
|
|
})
|
|
|
|
if err != nil {
|
|
c.Ui.Error(fmt.Sprintf("Failed to load backend: %s", err))
|
|
return 1
|
|
}
|
|
|
|
// We require a local backend
|
|
local, ok := b.(backend.Local)
|
|
if !ok {
|
|
c.Ui.Error(ErrUnsupportedLocalOp)
|
|
return 1
|
|
}
|
|
|
|
// Build the operation
|
|
opReq := c.Operation()
|
|
opReq.Module = mod
|
|
|
|
// Get the context
|
|
ctx, _, err := local.Context(opReq)
|
|
if err != nil {
|
|
c.Ui.Error(err.Error())
|
|
return 1
|
|
}
|
|
|
|
defer func() {
|
|
err := opReq.StateLocker.Unlock(nil)
|
|
if err != nil {
|
|
c.Ui.Error(err.Error())
|
|
}
|
|
}()
|
|
|
|
// Setup the UI so we can output directly to stdout
|
|
ui := &cli.BasicUi{
|
|
Writer: wrappedstreams.Stdout(),
|
|
ErrorWriter: wrappedstreams.Stderr(),
|
|
}
|
|
|
|
// IO Loop
|
|
session := &repl.Session{
|
|
Interpolater: ctx.Interpolater(),
|
|
}
|
|
|
|
// Determine if stdin is a pipe. If so, we evaluate directly.
|
|
if c.StdinPiped() {
|
|
return c.modePiped(session, ui)
|
|
}
|
|
|
|
return c.modeInteractive(session, ui)
|
|
}
|
|
|
|
func (c *ConsoleCommand) modePiped(session *repl.Session, ui cli.Ui) int {
|
|
var lastResult string
|
|
scanner := bufio.NewScanner(wrappedstreams.Stdin())
|
|
for scanner.Scan() {
|
|
// Handle it. If there is an error exit immediately
|
|
result, err := session.Handle(strings.TrimSpace(scanner.Text()))
|
|
if err != nil {
|
|
ui.Error(err.Error())
|
|
return 1
|
|
}
|
|
|
|
// Store the last result
|
|
lastResult = result
|
|
}
|
|
|
|
// Output the final result
|
|
ui.Output(lastResult)
|
|
|
|
return 0
|
|
}
|
|
|
|
func (c *ConsoleCommand) Help() string {
|
|
helpText := `
|
|
Usage: terraform console [options] [DIR]
|
|
|
|
Starts an interactive console for experimenting with Terraform
|
|
interpolations.
|
|
|
|
This will open an interactive console that you can use to type
|
|
interpolations into and inspect their values. This command loads the
|
|
current state. This lets you explore and test interpolations before
|
|
using them in future configurations.
|
|
|
|
This command will never modify your state.
|
|
|
|
DIR can be set to a directory with a Terraform state to load. By
|
|
default, this will default to the current working directory.
|
|
|
|
Options:
|
|
|
|
-state=path Path to read state. Defaults to "terraform.tfstate"
|
|
|
|
-var 'foo=bar' Set a variable in the Terraform configuration. This
|
|
flag can be set multiple times.
|
|
|
|
-var-file=foo Set variables in the Terraform configuration from
|
|
a file. If "terraform.tfvars" or any ".auto.tfvars"
|
|
files are present, they will be automatically loaded.
|
|
|
|
|
|
`
|
|
return strings.TrimSpace(helpText)
|
|
}
|
|
|
|
func (c *ConsoleCommand) Synopsis() string {
|
|
return "Interactive console for Terraform interpolations"
|
|
}
|