Merge pull request #27786 from hashicorp/alisdair/refresh-empty-diag
backend/local: Return diag for refresh empty state
This commit is contained in:
commit
1301e38caa
|
@ -5,7 +5,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/hashicorp/errwrap"
|
"github.com/hashicorp/errwrap"
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
|
@ -66,14 +65,11 @@ func (b *Local) opRefresh(
|
||||||
// Set our state
|
// Set our state
|
||||||
runningOp.State = opState.State()
|
runningOp.State = opState.State()
|
||||||
if !runningOp.State.HasResources() {
|
if !runningOp.State.HasResources() {
|
||||||
if b.CLI != nil {
|
|
||||||
diags = diags.Append(tfdiags.Sourceless(
|
diags = diags.Append(tfdiags.Sourceless(
|
||||||
tfdiags.Warning,
|
tfdiags.Warning,
|
||||||
"Empty or non-existent state",
|
"Empty or non-existent state",
|
||||||
"There are currently no resources tracked in the state, so there is nothing to refresh.",
|
"There are currently no resources tracked in the state, so there is nothing to refresh.",
|
||||||
))
|
))
|
||||||
b.CLI.Output(b.Colorize().Color(strings.TrimSpace(refreshNoState) + "\n"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform the refresh in a goroutine so we can be interrupted
|
// Perform the refresh in a goroutine so we can be interrupted
|
||||||
|
@ -90,7 +86,7 @@ func (b *Local) opRefresh(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// write the resulting state to the running op
|
// Write the resulting state to the running op
|
||||||
runningOp.State = newState
|
runningOp.State = newState
|
||||||
diags = diags.Append(refreshDiags)
|
diags = diags.Append(refreshDiags)
|
||||||
if refreshDiags.HasErrors() {
|
if refreshDiags.HasErrors() {
|
||||||
|
@ -104,12 +100,7 @@ func (b *Local) opRefresh(
|
||||||
op.ReportResult(runningOp, diags)
|
op.ReportResult(runningOp, diags)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show any remaining warnings before exiting
|
||||||
|
op.ReportResult(runningOp, diags)
|
||||||
}
|
}
|
||||||
|
|
||||||
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.
|
|
||||||
`
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package local
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/addrs"
|
"github.com/hashicorp/terraform/addrs"
|
||||||
|
@ -214,6 +215,42 @@ func TestLocal_refresh_context_error(t *testing.T) {
|
||||||
assertBackendStateUnlocked(t, b)
|
assertBackendStateUnlocked(t, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLocal_refreshEmptyState(t *testing.T) {
|
||||||
|
b, cleanup := TestLocal(t)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
p := TestLocalProvider(t, b, "test", refreshFixtureSchema())
|
||||||
|
testStateFile(t, b.StatePath, states.NewState())
|
||||||
|
|
||||||
|
p.ReadResourceFn = nil
|
||||||
|
p.ReadResourceResponse = &providers.ReadResourceResponse{NewState: cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"id": cty.StringVal("yes"),
|
||||||
|
})}
|
||||||
|
|
||||||
|
op, configCleanup := testOperationRefresh(t, "./testdata/refresh")
|
||||||
|
defer configCleanup()
|
||||||
|
|
||||||
|
record, playback := testRecordDiagnostics(t)
|
||||||
|
op.ShowDiagnostics = record
|
||||||
|
|
||||||
|
run, err := b.Operation(context.Background(), op)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad: %s", err)
|
||||||
|
}
|
||||||
|
<-run.Done()
|
||||||
|
|
||||||
|
diags := playback()
|
||||||
|
if diags.HasErrors() {
|
||||||
|
t.Fatalf("expected only warning diags, got errors: %s", diags.Err())
|
||||||
|
}
|
||||||
|
if got, want := diags.ErrWithWarnings().Error(), "Empty or non-existent state"; !strings.Contains(got, want) {
|
||||||
|
t.Errorf("wrong diags\n got: %s\nwant: %s", got, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
// the backend should be unlocked after a run
|
||||||
|
assertBackendStateUnlocked(t, b)
|
||||||
|
}
|
||||||
|
|
||||||
func testOperationRefresh(t *testing.T, configDir string) (*backend.Operation, func()) {
|
func testOperationRefresh(t *testing.T, configDir string) (*backend.Operation, func()) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue