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
|
||||
Targets []string
|
||||
Variables map[string]interface{}
|
||||
AutoApprove bool
|
||||
|
||||
// Input/output/control options.
|
||||
UIIn terraform.UIInput
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/hashicorp/terraform/backend"
|
||||
"github.com/hashicorp/terraform/command/clistate"
|
||||
"github.com/hashicorp/terraform/command/format"
|
||||
"github.com/hashicorp/terraform/config/module"
|
||||
"github.com/hashicorp/terraform/state"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
|
@ -89,10 +90,37 @@ func (b *Local) opApply(
|
|||
|
||||
// Perform the 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)
|
||||
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
|
||||
|
@ -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
|
||||
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 {
|
||||
var destroyForce, refresh bool
|
||||
var destroyForce, refresh, autoApprove bool
|
||||
args = c.Meta.process(args, true)
|
||||
|
||||
cmdName := "apply"
|
||||
|
@ -42,6 +42,9 @@ func (c *ApplyCommand) Run(args []string) int {
|
|||
cmdFlags.BoolVar(&destroyForce, "force", false, "force")
|
||||
}
|
||||
cmdFlags.BoolVar(&refresh, "refresh", true, "refresh")
|
||||
if !c.Destroy {
|
||||
cmdFlags.BoolVar(&autoApprove, "auto-approve", true, "skip interactive approval of plan before applying")
|
||||
}
|
||||
cmdFlags.IntVar(
|
||||
&c.Meta.parallelism, "parallelism", DefaultParallelism, "parallelism")
|
||||
cmdFlags.StringVar(&c.Meta.statePath, "state", "", "path")
|
||||
|
@ -112,6 +115,11 @@ func (c *ApplyCommand) Run(args []string) int {
|
|||
if plan != nil {
|
||||
// Reset the config path for backend loading
|
||||
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)
|
||||
|
@ -195,6 +203,7 @@ func (c *ApplyCommand) Run(args []string) int {
|
|||
opReq.Plan = plan
|
||||
opReq.PlanRefresh = refresh
|
||||
opReq.Type = backend.OperationTypeApply
|
||||
opReq.AutoApprove = autoApprove
|
||||
|
||||
// Perform the operation
|
||||
ctx, ctxCancel := context.WithCancel(context.Background())
|
||||
|
@ -289,6 +298,10 @@ Options:
|
|||
|
||||
-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.
|
||||
|
||||
-no-color If specified, output won't contain any color.
|
||||
|
|
|
@ -168,6 +168,7 @@ func (m *Meta) Operation() *backend.Operation {
|
|||
PlanOutBackend: m.backendState,
|
||||
Targets: m.targets,
|
||||
UIIn: m.UIInput(),
|
||||
UIOut: m.Ui,
|
||||
Workspace: m.Workspace(),
|
||||
LockState: m.stateLock,
|
||||
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.
|
||||
|
||||
* `-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.
|
||||
|
||||
* `-parallelism=n` - Limit the number of concurrent operation as Terraform
|
||||
|
|
Loading…
Reference in New Issue