Skip to content

Commit

Permalink
Merge pull request #19035 from hashicorp/f-policy-override
Browse files Browse the repository at this point in the history
backend/remote: don’t ask questions when -auto-approve is set
  • Loading branch information
Sander van Harmelen authored Oct 10, 2018
2 parents 15dda63 + d78470a commit 4586b9f
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 86 deletions.
2 changes: 1 addition & 1 deletion backend/local/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ func (b *Local) Operation(ctx context.Context, op *backend.Operation) (*backend.
return runningOp, nil
}

// opWait wats for the operation to complete, and a stop signal or a
// opWait waits for the operation to complete, and a stop signal or a
// cancelation signal.
func (b *Local) opWait(
doneCh <-chan struct{},
Expand Down
2 changes: 1 addition & 1 deletion backend/remote/backend_apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ func (b *Remote) checkPolicy(stopCtx, cancelCtx context.Context, op *backend.Ope
case tfe.PolicyHardFailed:
return fmt.Errorf(msgPrefix + " hard failed.")
case tfe.PolicySoftFailed:
if op.UIOut == nil || op.UIIn == nil ||
if op.UIOut == nil || op.UIIn == nil || op.AutoApprove ||
!pc.Actions.IsOverridable || !pc.Permissions.CanOverride {
return fmt.Errorf(msgPrefix + " soft failed.")
}
Expand Down
170 changes: 86 additions & 84 deletions backend/remote/backend_apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,61 +66,6 @@ func TestRemote_applyBasic(t *testing.T) {
}
}

func TestRemote_applyWithAutoApply(t *testing.T) {
b := testBackendNoDefault(t)

// Create a named workspace that auto applies.
_, err := b.client.Workspaces.Create(
context.Background(),
b.organization,
tfe.WorkspaceCreateOptions{
AutoApply: tfe.Bool(true),
Name: tfe.String(b.prefix + "prod"),
},
)
if err != nil {
t.Fatalf("error creating named workspace: %v", err)
}

mod, modCleanup := module.TestTree(t, "./test-fixtures/apply")
defer modCleanup()

input := testInput(t, map[string]string{
"approve": "yes",
})

op := testOperationApply()
op.Module = mod
op.UIIn = input
op.UIOut = b.CLI
op.Workspace = "prod"

run, err := b.Operation(context.Background(), op)
if err != nil {
t.Fatalf("error starting operation: %v", err)
}

<-run.Done()
if run.Err != nil {
t.Fatalf("error running operation: %v", run.Err)
}
if run.PlanEmpty {
t.Fatalf("expected a non-empty plan")
}

if len(input.answers) != 1 {
t.Fatalf("expected an unused answer, got: %v", input.answers)
}

output := b.CLI.(*cli.MockUi).OutputWriter.String()
if !strings.Contains(output, "1 to add, 0 to change, 0 to destroy") {
t.Fatalf("missing plan summery in output: %s", output)
}
if !strings.Contains(output, "1 added, 0 changed, 0 destroyed") {
t.Fatalf("missing apply summery in output: %s", output)
}
}

func TestRemote_applyWithoutPermissions(t *testing.T) {
b := testBackendNoDefault(t)

Expand Down Expand Up @@ -461,6 +406,61 @@ func TestRemote_applyAutoApprove(t *testing.T) {
}
}

func TestRemote_applyWithAutoApply(t *testing.T) {
b := testBackendNoDefault(t)

// Create a named workspace that auto applies.
_, err := b.client.Workspaces.Create(
context.Background(),
b.organization,
tfe.WorkspaceCreateOptions{
AutoApply: tfe.Bool(true),
Name: tfe.String(b.prefix + "prod"),
},
)
if err != nil {
t.Fatalf("error creating named workspace: %v", err)
}

mod, modCleanup := module.TestTree(t, "./test-fixtures/apply")
defer modCleanup()

input := testInput(t, map[string]string{
"approve": "yes",
})

op := testOperationApply()
op.Module = mod
op.UIIn = input
op.UIOut = b.CLI
op.Workspace = "prod"

run, err := b.Operation(context.Background(), op)
if err != nil {
t.Fatalf("error starting operation: %v", err)
}

<-run.Done()
if run.Err != nil {
t.Fatalf("error running operation: %v", run.Err)
}
if run.PlanEmpty {
t.Fatalf("expected a non-empty plan")
}

if len(input.answers) != 1 {
t.Fatalf("expected an unused answer, got: %v", input.answers)
}

output := b.CLI.(*cli.MockUi).OutputWriter.String()
if !strings.Contains(output, "1 to add, 0 to change, 0 to destroy") {
t.Fatalf("missing plan summery in output: %s", output)
}
if !strings.Contains(output, "1 added, 0 changed, 0 destroyed") {
t.Fatalf("missing apply summery in output: %s", output)
}
}

func TestRemote_applyLockTimeout(t *testing.T) {
b := testBackendDefault(t)
ctx := context.Background()
Expand Down Expand Up @@ -745,51 +745,40 @@ func TestRemote_applyPolicySoftFail(t *testing.T) {
}
}

func TestRemote_applyPolicySoftFailAutoApply(t *testing.T) {
func TestRemote_applyPolicySoftFailAutoApprove(t *testing.T) {
b := testBackendDefault(t)

// Create a named workspace that auto applies.
_, err := b.client.Workspaces.Create(
context.Background(),
b.organization,
tfe.WorkspaceCreateOptions{
AutoApply: tfe.Bool(true),
Name: tfe.String(b.prefix + "prod"),
},
)
if err != nil {
t.Fatalf("error creating named workspace: %v", err)
}

mod, modCleanup := module.TestTree(t, "./test-fixtures/apply-policy-soft-failed")
defer modCleanup()

input := testInput(t, map[string]string{
"override": "override",
"approve": "yes",
})

op := testOperationApply()
op.AutoApprove = true
op.Module = mod
op.UIIn = input
op.UIOut = b.CLI
op.Workspace = "prod"
op.Workspace = backend.DefaultStateName

run, err := b.Operation(context.Background(), op)
if err != nil {
t.Fatalf("error starting operation: %v", err)
}

<-run.Done()
if run.Err != nil {
t.Fatalf("error running operation: %v", run.Err)
if run.Err == nil {
t.Fatalf("expected an apply error, got: %v", run.Err)
}
if run.PlanEmpty {
t.Fatalf("expected a non-empty plan")
if !run.PlanEmpty {
t.Fatalf("expected plan to be empty")
}
if !strings.Contains(run.Err.Error(), "soft failed") {
t.Fatalf("expected a policy check error, got: %v", run.Err)
}

if len(input.answers) != 1 {
t.Fatalf("expected an unused answer, got: %v", input.answers)
t.Fatalf("expected an unused answers, got: %v", input.answers)
}

output := b.CLI.(*cli.MockUi).OutputWriter.String()
Expand All @@ -799,27 +788,40 @@ func TestRemote_applyPolicySoftFailAutoApply(t *testing.T) {
if !strings.Contains(output, "Sentinel Result: false") {
t.Fatalf("missing policy check result in output: %s", output)
}
if !strings.Contains(output, "1 added, 0 changed, 0 destroyed") {
t.Fatalf("missing apply summery in output: %s", output)
if strings.Contains(output, "1 added, 0 changed, 0 destroyed") {
t.Fatalf("unexpected apply summery in output: %s", output)
}
}

func TestRemote_applyPolicySoftFailAutoApprove(t *testing.T) {
func TestRemote_applyPolicySoftFailAutoApply(t *testing.T) {
b := testBackendDefault(t)

// Create a named workspace that auto applies.
_, err := b.client.Workspaces.Create(
context.Background(),
b.organization,
tfe.WorkspaceCreateOptions{
AutoApply: tfe.Bool(true),
Name: tfe.String(b.prefix + "prod"),
},
)
if err != nil {
t.Fatalf("error creating named workspace: %v", err)
}

mod, modCleanup := module.TestTree(t, "./test-fixtures/apply-policy-soft-failed")
defer modCleanup()

input := testInput(t, map[string]string{
"override": "override",
"approve": "yes",
})

op := testOperationApply()
op.AutoApprove = true
op.Module = mod
op.UIIn = input
op.UIOut = b.CLI
op.Workspace = backend.DefaultStateName
op.Workspace = "prod"

run, err := b.Operation(context.Background(), op)
if err != nil {
Expand All @@ -834,8 +836,8 @@ func TestRemote_applyPolicySoftFailAutoApprove(t *testing.T) {
t.Fatalf("expected a non-empty plan")
}

if len(input.answers) > 0 {
t.Fatalf("expected no unused answers, got: %v", input.answers)
if len(input.answers) != 1 {
t.Fatalf("expected an unused answer, got: %v", input.answers)
}

output := b.CLI.(*cli.MockUi).OutputWriter.String()
Expand Down

0 comments on commit 4586b9f

Please sign in to comment.