mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
Merge pull request #30858 from hashicorp/sebasslash/err-approval-input-false
Handle -input=false in cloud integration
This commit is contained in:
commit
8089f090f9
@ -44,7 +44,8 @@ BUG FIXES:
|
||||
* When rendering a diff, Terraform now quotes the name of any object attribute whose string representation is not a valid identifier. ([#30766](https://github.com/hashicorp/terraform/issues/30766))
|
||||
* Terraform will prioritize local terraform variables over remote terraform variables in operations such as `import`, `plan`, `refresh` and `apply` for workspaces in local execution mode. This behavior applies to both `remote` backend and the `cloud` integration configuration. ([#29972](https://github.com/hashicorp/terraform/issues/29972))
|
||||
* `terraform show -json`: JSON plan output now correctly maps aliased providers to their configurations, and includes the full provider source address alongside the short provider name. ([#30138](https://github.com/hashicorp/terraform/issues/30138))
|
||||
* The local token configuration now has higher priority than the token specified in a CLI configuration. ([#30664](https://github.com/hashicorp/terraform/issues/30664))
|
||||
* The local token configuration in the `cloud` and `remote` backend now has higher priority than the token specified in a CLI configuration. ([#30664](https://github.com/hashicorp/terraform/issues/30664))
|
||||
* The `cloud` integration now gracefully exits when `-input=false` and an operation requires some user input.
|
||||
|
||||
## Previous Releases
|
||||
|
||||
|
@ -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",
|
||||
|
58
internal/cloud/e2e/apply_no_input_flag_test.go
Normal file
58
internal/cloud/e2e/apply_no_input_flag_test.go
Normal file
@ -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…
Reference in New Issue
Block a user