command: add "apply -auto-approve=false" flag
A common reason to want to use `terraform plan` is to have a chance to review and confirm a plan before running it. If in fact that is the only reason you are running plan, this new `terraform apply -auto-approve=false` flag provides an easier alternative to P=$(mktemp -t plan) terraform refresh terraform plan -refresh=false -out=$P terraform apply $P rm $P The flag defaults to true for now, but in a future version of Terraform it will default to false.
This commit is contained in:
parent
e7f7395e9e
commit
039d36bf91
|
@ -124,6 +124,7 @@ type Operation struct {
|
||||||
Destroy bool
|
Destroy bool
|
||||||
Targets []string
|
Targets []string
|
||||||
Variables map[string]interface{}
|
Variables map[string]interface{}
|
||||||
|
AutoApprove bool
|
||||||
|
|
||||||
// Input/output/control options.
|
// Input/output/control options.
|
||||||
UIIn terraform.UIInput
|
UIIn terraform.UIInput
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/command/clistate"
|
"github.com/hashicorp/terraform/command/clistate"
|
||||||
|
"github.com/hashicorp/terraform/command/format"
|
||||||
"github.com/hashicorp/terraform/config/module"
|
"github.com/hashicorp/terraform/config/module"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/state"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
@ -89,10 +90,37 @@ func (b *Local) opApply(
|
||||||
|
|
||||||
// Perform the plan
|
// Perform the plan
|
||||||
log.Printf("[INFO] backend/local: apply calling Plan")
|
log.Printf("[INFO] backend/local: apply calling Plan")
|
||||||
if _, err := tfCtx.Plan(); err != nil {
|
plan, err := tfCtx.Plan()
|
||||||
|
if err != nil {
|
||||||
runningOp.Err = errwrap.Wrapf("Error running plan: {{err}}", err)
|
runningOp.Err = errwrap.Wrapf("Error running plan: {{err}}", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trivialPlan := plan.Diff == nil || plan.Diff.Empty()
|
||||||
|
hasUI := op.UIOut != nil && op.UIIn != nil
|
||||||
|
if hasUI && !op.AutoApprove && !trivialPlan {
|
||||||
|
op.UIOut.Output(strings.TrimSpace(approvePlanHeader) + "\n")
|
||||||
|
op.UIOut.Output(format.Plan(&format.PlanOpts{
|
||||||
|
Plan: plan,
|
||||||
|
Color: b.Colorize(),
|
||||||
|
ModuleDepth: -1,
|
||||||
|
}))
|
||||||
|
desc := "Terraform will apply the plan described above.\n" +
|
||||||
|
"Only 'yes' will be accepted to approve."
|
||||||
|
v, err := op.UIIn.Input(&terraform.InputOpts{
|
||||||
|
Id: "approve",
|
||||||
|
Query: "Do you want to apply the plan above?",
|
||||||
|
Description: desc,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
runningOp.Err = errwrap.Wrapf("Error asking for approval: {{err}}", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if v != "yes" {
|
||||||
|
runningOp.Err = errors.New("Apply cancelled.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup our hook for continuous state updates
|
// Setup our hook for continuous state updates
|
||||||
|
@ -288,3 +316,11 @@ Terraform encountered an error attempting to save the state before canceling
|
||||||
the current operation. Once the operation is complete another attempt will be
|
the current operation. Once the operation is complete another attempt will be
|
||||||
made to save the final state.
|
made to save the final state.
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const approvePlanHeader = `
|
||||||
|
The Terraform execution plan has been generated and is shown below.
|
||||||
|
Resources are shown in alphabetical order for quick scanning. Green resources
|
||||||
|
will be created (or destroyed and then created if an existing resource
|
||||||
|
exists), yellow resources are being changed in-place, and red resources
|
||||||
|
will be destroyed. Cyan entries are data sources to be read.
|
||||||
|
`
|
||||||
|
|
|
@ -29,7 +29,7 @@ type ApplyCommand struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ApplyCommand) Run(args []string) int {
|
func (c *ApplyCommand) Run(args []string) int {
|
||||||
var destroyForce, refresh bool
|
var destroyForce, refresh, autoApprove bool
|
||||||
args = c.Meta.process(args, true)
|
args = c.Meta.process(args, true)
|
||||||
|
|
||||||
cmdName := "apply"
|
cmdName := "apply"
|
||||||
|
@ -42,6 +42,9 @@ func (c *ApplyCommand) Run(args []string) int {
|
||||||
cmdFlags.BoolVar(&destroyForce, "force", false, "force")
|
cmdFlags.BoolVar(&destroyForce, "force", false, "force")
|
||||||
}
|
}
|
||||||
cmdFlags.BoolVar(&refresh, "refresh", true, "refresh")
|
cmdFlags.BoolVar(&refresh, "refresh", true, "refresh")
|
||||||
|
if !c.Destroy {
|
||||||
|
cmdFlags.BoolVar(&autoApprove, "auto-approve", true, "skip interactive approval of plan before applying")
|
||||||
|
}
|
||||||
cmdFlags.IntVar(
|
cmdFlags.IntVar(
|
||||||
&c.Meta.parallelism, "parallelism", DefaultParallelism, "parallelism")
|
&c.Meta.parallelism, "parallelism", DefaultParallelism, "parallelism")
|
||||||
cmdFlags.StringVar(&c.Meta.statePath, "state", "", "path")
|
cmdFlags.StringVar(&c.Meta.statePath, "state", "", "path")
|
||||||
|
@ -112,6 +115,11 @@ func (c *ApplyCommand) Run(args []string) int {
|
||||||
if plan != nil {
|
if plan != nil {
|
||||||
// Reset the config path for backend loading
|
// Reset the config path for backend loading
|
||||||
configPath = ""
|
configPath = ""
|
||||||
|
|
||||||
|
if !autoApprove {
|
||||||
|
c.Ui.Error("Cannot combine -auto-approve=false with a plan file.")
|
||||||
|
return 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the module if we don't have one yet (not running from plan)
|
// Load the module if we don't have one yet (not running from plan)
|
||||||
|
@ -195,6 +203,7 @@ func (c *ApplyCommand) Run(args []string) int {
|
||||||
opReq.Plan = plan
|
opReq.Plan = plan
|
||||||
opReq.PlanRefresh = refresh
|
opReq.PlanRefresh = refresh
|
||||||
opReq.Type = backend.OperationTypeApply
|
opReq.Type = backend.OperationTypeApply
|
||||||
|
opReq.AutoApprove = autoApprove
|
||||||
|
|
||||||
// Perform the operation
|
// Perform the operation
|
||||||
ctx, ctxCancel := context.WithCancel(context.Background())
|
ctx, ctxCancel := context.WithCancel(context.Background())
|
||||||
|
@ -289,6 +298,10 @@ Options:
|
||||||
|
|
||||||
-lock-timeout=0s Duration to retry a state lock.
|
-lock-timeout=0s Duration to retry a state lock.
|
||||||
|
|
||||||
|
-auto-approve=true Skip interactive approval of plan before applying. In a
|
||||||
|
future version of Terraform, this flag's default value
|
||||||
|
will change to false.
|
||||||
|
|
||||||
-input=true Ask for input for variables if not directly set.
|
-input=true Ask for input for variables if not directly set.
|
||||||
|
|
||||||
-no-color If specified, output won't contain any color.
|
-no-color If specified, output won't contain any color.
|
||||||
|
|
|
@ -168,6 +168,7 @@ func (m *Meta) Operation() *backend.Operation {
|
||||||
PlanOutBackend: m.backendState,
|
PlanOutBackend: m.backendState,
|
||||||
Targets: m.targets,
|
Targets: m.targets,
|
||||||
UIIn: m.UIInput(),
|
UIIn: m.UIInput(),
|
||||||
|
UIOut: m.Ui,
|
||||||
Workspace: m.Workspace(),
|
Workspace: m.Workspace(),
|
||||||
LockState: m.stateLock,
|
LockState: m.stateLock,
|
||||||
StateLockTimeout: m.stateLockTimeout,
|
StateLockTimeout: m.stateLockTimeout,
|
||||||
|
|
|
@ -37,6 +37,9 @@ The command-line flags are all optional. The list of available flags are:
|
||||||
|
|
||||||
* `-input=true` - Ask for input for variables if not directly set.
|
* `-input=true` - Ask for input for variables if not directly set.
|
||||||
|
|
||||||
|
* `-auto-approve=true` - Skip interactive approval of plan before applying. In a
|
||||||
|
future version of Terraform, this flag's default value will change to false.
|
||||||
|
|
||||||
* `-no-color` - Disables output with coloring.
|
* `-no-color` - Disables output with coloring.
|
||||||
|
|
||||||
* `-parallelism=n` - Limit the number of concurrent operation as Terraform
|
* `-parallelism=n` - Limit the number of concurrent operation as Terraform
|
||||||
|
|
Loading…
Reference in New Issue