Merge pull request #12777 from hashicorp/b-refresh-empty
backend/local: allow refresh on empty/non-existent state
This commit is contained in:
commit
6921457601
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
|
@ -22,24 +23,17 @@ func (b *Local) opRefresh(
|
|||
if b.Backend == nil {
|
||||
if _, err := os.Stat(b.StatePath); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
runningOp.Err = fmt.Errorf(
|
||||
"The Terraform state file for your infrastructure does not\n"+
|
||||
"exist. The 'refresh' command only works and only makes sense\n"+
|
||||
"when there is existing state that Terraform is managing. Please\n"+
|
||||
"double-check the value given below and try again. If you\n"+
|
||||
"haven't created infrastructure with Terraform yet, use the\n"+
|
||||
"'terraform apply' command.\n\n"+
|
||||
"Path: %s",
|
||||
b.StatePath)
|
||||
return
|
||||
err = nil
|
||||
}
|
||||
|
||||
runningOp.Err = fmt.Errorf(
|
||||
"There was an error reading the Terraform state that is needed\n"+
|
||||
"for refreshing. The path and error are shown below.\n\n"+
|
||||
"Path: %s\n\nError: %s",
|
||||
b.StatePath, err)
|
||||
return
|
||||
if err != nil {
|
||||
runningOp.Err = fmt.Errorf(
|
||||
"There was an error reading the Terraform state that is needed\n"+
|
||||
"for refreshing. The path and error are shown below.\n\n"+
|
||||
"Path: %s\n\nError: %s",
|
||||
b.StatePath, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,6 +68,12 @@ func (b *Local) opRefresh(
|
|||
|
||||
// Set our state
|
||||
runningOp.State = opState.State()
|
||||
if runningOp.State.Empty() || !runningOp.State.HasResources() {
|
||||
if b.CLI != nil {
|
||||
b.CLI.Output(b.Colorize().Color(
|
||||
strings.TrimSpace(refreshNoState) + "\n"))
|
||||
}
|
||||
}
|
||||
|
||||
// Perform operation and write the resulting state to the running op
|
||||
newState, err := tfCtx.Refresh()
|
||||
|
@ -93,3 +93,11 @@ func (b *Local) opRefresh(
|
|||
return
|
||||
}
|
||||
}
|
||||
|
||||
const refreshNoState = `
|
||||
[reset][bold][yellow]Empty or non-existent state file.[reset][yellow]
|
||||
|
||||
Refresh will do nothing. Refresh does not error or return an erroneous
|
||||
exit status because many automation scripts use refresh, plan, then apply
|
||||
and may not have a state file yet for the first run.
|
||||
`
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/copy"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
@ -59,6 +60,37 @@ func TestRefresh(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestRefresh_empty(t *testing.T) {
|
||||
// Create a temporary working directory that is empty
|
||||
td := tempDir(t)
|
||||
copy.CopyDir(testFixturePath("refresh-empty"), td)
|
||||
defer os.RemoveAll(td)
|
||||
defer testChdir(t, td)()
|
||||
|
||||
p := testProvider()
|
||||
ui := new(cli.MockUi)
|
||||
c := &RefreshCommand{
|
||||
Meta: Meta{
|
||||
ContextOpts: testCtxConfig(p),
|
||||
Ui: ui,
|
||||
},
|
||||
}
|
||||
|
||||
p.RefreshFn = nil
|
||||
p.RefreshReturn = &terraform.InstanceState{ID: "yes"}
|
||||
|
||||
args := []string{
|
||||
td,
|
||||
}
|
||||
if code := c.Run(args); code != 0 {
|
||||
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
||||
}
|
||||
|
||||
if p.RefreshCalled {
|
||||
t.Fatal("refresh should not be called")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRefresh_lockedState(t *testing.T) {
|
||||
state := testState()
|
||||
statePath := testStateFile(t, state)
|
||||
|
@ -96,25 +128,6 @@ func TestRefresh_lockedState(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestRefresh_badState(t *testing.T) {
|
||||
p := testProvider()
|
||||
ui := new(cli.MockUi)
|
||||
c := &RefreshCommand{
|
||||
Meta: Meta{
|
||||
ContextOpts: testCtxConfig(p),
|
||||
Ui: ui,
|
||||
},
|
||||
}
|
||||
|
||||
args := []string{
|
||||
"-state", "i-should-not-exist-ever",
|
||||
testFixturePath("refresh"),
|
||||
}
|
||||
if code := c.Run(args); code != 1 {
|
||||
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestRefresh_cwd(t *testing.T) {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
# Hello
|
Loading…
Reference in New Issue