Merge pull request #11989 from hashicorp/b-backend-local
backend/local: check for empty config on apply
This commit is contained in:
commit
f231ca3d5a
|
@ -4,11 +4,13 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/errwrap"
|
"github.com/hashicorp/errwrap"
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
clistate "github.com/hashicorp/terraform/command/state"
|
clistate "github.com/hashicorp/terraform/command/state"
|
||||||
|
"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"
|
||||||
)
|
)
|
||||||
|
@ -19,6 +21,19 @@ func (b *Local) opApply(
|
||||||
runningOp *backend.RunningOperation) {
|
runningOp *backend.RunningOperation) {
|
||||||
log.Printf("[INFO] backend/local: starting Apply operation")
|
log.Printf("[INFO] backend/local: starting Apply operation")
|
||||||
|
|
||||||
|
// If we have a nil module at this point, then set it to an empty tree
|
||||||
|
// to avoid any potential crashes.
|
||||||
|
if op.Plan == nil && op.Module == nil && !op.Destroy {
|
||||||
|
runningOp.Err = fmt.Errorf(strings.TrimSpace(applyErrNoConfig))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have a nil module at this point, then set it to an empty tree
|
||||||
|
// to avoid any potential crashes.
|
||||||
|
if op.Module == nil {
|
||||||
|
op.Module = module.NewEmptyTree()
|
||||||
|
}
|
||||||
|
|
||||||
// Setup our count hook that keeps track of resource changes
|
// Setup our count hook that keeps track of resource changes
|
||||||
countHook := new(CountHook)
|
countHook := new(CountHook)
|
||||||
stateHook := new(StateHook)
|
stateHook := new(StateHook)
|
||||||
|
@ -165,3 +180,12 @@ func (b *Local) opApply(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const applyErrNoConfig = `
|
||||||
|
No configuration files found!
|
||||||
|
|
||||||
|
Apply requires configuration to be present. Applying without a configuration
|
||||||
|
would mark everything for destruction, which is normally not what is desired.
|
||||||
|
If you would like to destroy everything, please run 'terraform destroy' instead
|
||||||
|
which does not require any configuration files.
|
||||||
|
`
|
||||||
|
|
|
@ -3,6 +3,7 @@ package local
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -50,6 +51,59 @@ test_instance.foo:
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLocal_applyEmptyDir(t *testing.T) {
|
||||||
|
b := TestLocal(t)
|
||||||
|
p := TestLocalProvider(t, b, "test")
|
||||||
|
|
||||||
|
p.ApplyReturn = &terraform.InstanceState{ID: "yes"}
|
||||||
|
|
||||||
|
op := testOperationApply()
|
||||||
|
op.Module = nil
|
||||||
|
|
||||||
|
run, err := b.Operation(context.Background(), op)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad: %s", err)
|
||||||
|
}
|
||||||
|
<-run.Done()
|
||||||
|
if run.Err == nil {
|
||||||
|
t.Fatal("should error")
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.ApplyCalled {
|
||||||
|
t.Fatal("apply should not be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := os.Stat(b.StateOutPath); err == nil {
|
||||||
|
t.Fatal("should not exist")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocal_applyEmptyDirDestroy(t *testing.T) {
|
||||||
|
b := TestLocal(t)
|
||||||
|
p := TestLocalProvider(t, b, "test")
|
||||||
|
|
||||||
|
p.ApplyReturn = nil
|
||||||
|
|
||||||
|
op := testOperationApply()
|
||||||
|
op.Module = nil
|
||||||
|
op.Destroy = true
|
||||||
|
|
||||||
|
run, err := b.Operation(context.Background(), op)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad: %s", err)
|
||||||
|
}
|
||||||
|
<-run.Done()
|
||||||
|
if run.Err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.ApplyCalled {
|
||||||
|
t.Fatal("apply should not be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
checkState(t, b.StateOutPath, `<no state>`)
|
||||||
|
}
|
||||||
|
|
||||||
func TestLocal_applyError(t *testing.T) {
|
func TestLocal_applyError(t *testing.T) {
|
||||||
b := TestLocal(t)
|
b := TestLocal(t)
|
||||||
p := TestLocalProvider(t, b, "test")
|
p := TestLocalProvider(t, b, "test")
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
This is an empty dir
|
Loading…
Reference in New Issue