Handle -input=false in cloud integration

For non-interactive contexts, Terraform is typically executed with the flag -input=false.
However for runs that are not set to auto approve, the cloud integration will prompt a user for
approval input even with input being set to false. This commit enables the cloud integration to know
the value of the input flag and use it to determine whether or not to ask the user for input.

If -input is set to false and the run cannot be auto approved, the cloud integration will throw an error
stating run confirmation can no longer be handled in the CLI and that they must do so through the browser.
sebasslash/err-approval-input-false
Sebastian Rivera 4 years ago
parent c557078704
commit 9d7fdbea2d

@ -89,6 +89,10 @@ type Cloud struct {
ignoreVersionConflict bool
runningInAutomation bool
// input stores the value of the -input flag, since it will be used
// to determine whether or not to ask the user for approval of a run.
input bool
}
var _ backend.Backend = (*Cloud)(nil)

@ -100,7 +100,7 @@ func (b *Cloud) opApply(stopCtx, cancelCtx context.Context, op *backend.Operatio
mustConfirm := (op.UIIn != nil && op.UIOut != nil) && !op.AutoApprove
if mustConfirm {
if mustConfirm && b.input {
opts := &terraform.InputOpts{Id: "approve"}
if op.PlanMode == plans.DestroyMode {
@ -117,6 +117,8 @@ func (b *Cloud) opApply(stopCtx, cancelCtx context.Context, op *backend.Operatio
if err != nil && err != errRunApproved {
return r, err
}
} else if mustConfirm && !b.input {
return r, errApplyNeedsUIConfirmation
} else {
// If we don't need to ask for confirmation, insert a blank
// line to separate the ouputs.

@ -16,6 +16,7 @@ func (b *Cloud) CLIInit(opts *backend.CLIOpts) error {
b.CLIColor = opts.CLIColor
b.ContextOpts = opts.ContextOpts
b.runningInAutomation = opts.RunningInAutomation
b.input = opts.Input
return nil
}

@ -3,7 +3,6 @@ package cloud
import (
"bufio"
"context"
"errors"
"fmt"
"io"
"math"
@ -17,14 +16,6 @@ import (
"github.com/hashicorp/terraform/internal/terraform"
)
var (
errApplyDiscarded = errors.New("Apply discarded.")
errDestroyDiscarded = errors.New("Destroy discarded.")
errRunApproved = errors.New("approved using the UI or API")
errRunDiscarded = errors.New("discarded using the UI or API")
errRunOverridden = errors.New("overridden using the UI or API")
)
var (
backoffMin = 1000.0
backoffMax = 3000.0
@ -388,6 +379,8 @@ func (b *Cloud) checkPolicy(stopCtx, cancelCtx context.Context, op *backend.Oper
if _, err = b.client.PolicyChecks.Override(stopCtx, pc.ID); err != nil {
return generalError(fmt.Sprintf("Failed to override policy check.\n%s", runUrl), err)
}
} else if !b.input {
return errPolicyOverrideNeedsUIConfirmation
} else {
opts := &terraform.InputOpts{
Id: "override",

@ -0,0 +1,58 @@
package main
import (
"testing"
)
func Test_apply_no_input_flag(t *testing.T) {
t.Parallel()
skipIfMissingEnvVar(t)
cases := testCases{
"terraform apply with -input=false": {
operations: []operationSets{
{
prep: func(t *testing.T, orgName, dir string) {
wsName := "new-workspace"
tfBlock := terraformConfigCloudBackendName(orgName, wsName)
writeMainTF(t, tfBlock, dir)
},
commands: []tfCommand{
{
command: []string{"init", "-input=false"},
expectedCmdOutput: `Terraform Cloud has been successfully initialized`,
},
{
command: []string{"apply", "-input=false"},
expectedCmdOutput: `Cannot confirm apply due to -input=false. Please handle run confirmation in the UI.`,
expectError: true,
},
},
},
},
},
"terraform apply with auto approve and -input=false": {
operations: []operationSets{
{
prep: func(t *testing.T, orgName, dir string) {
wsName := "cloud-workspace"
tfBlock := terraformConfigCloudBackendName(orgName, wsName)
writeMainTF(t, tfBlock, dir)
},
commands: []tfCommand{
{
command: []string{"init", "-input=false"},
expectedCmdOutput: `Terraform Cloud has been successfully initialized`,
},
{
command: []string{"apply", "-auto-approve", "-input=false"},
expectedCmdOutput: `Apply complete!`,
},
},
},
},
},
}
testRunner(t, cases, 1)
}

@ -1,6 +1,7 @@
package cloud
import (
"errors"
"fmt"
"strings"
@ -8,6 +9,18 @@ import (
"github.com/zclconf/go-cty/cty"
)
// String based errors
var (
errApplyDiscarded = errors.New("Apply discarded.")
errDestroyDiscarded = errors.New("Destroy discarded.")
errRunApproved = errors.New("approved using the UI or API")
errRunDiscarded = errors.New("discarded using the UI or API")
errRunOverridden = errors.New("overridden using the UI or API")
errApplyNeedsUIConfirmation = errors.New("Cannot confirm apply due to -input=false. Please handle run confirmation in the UI.")
errPolicyOverrideNeedsUIConfirmation = errors.New("Cannot override soft failed policy checks when -input=false. Please open the run in the UI to override.")
)
// Diagnostic error messages
var (
invalidWorkspaceConfigMissingValues = tfdiags.AttributeValue(
tfdiags.Error,

@ -154,6 +154,7 @@ func testBackend(t *testing.T, obj cty.Value) (*Cloud, func()) {
// Set local to a local test backend.
b.local = testLocalBackend(t, b)
b.input = true
ctx := context.Background()

Loading…
Cancel
Save