mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
command: Even more fixes for "apply" command tests
This commit is contained in:
parent
34a29315f7
commit
741d334ee4
@ -192,13 +192,14 @@ func (b *Local) contextFromPlanFile(pf *planfile.Reader, opts terraform.ContextO
|
|||||||
// has changed since the plan was created. (All of the "real-world"
|
// has changed since the plan was created. (All of the "real-world"
|
||||||
// state manager implementstions support this, but simpler test backends
|
// state manager implementstions support this, but simpler test backends
|
||||||
// may not.)
|
// may not.)
|
||||||
lineageOk := currentStateMeta.Lineage == "" || priorStateFile.Lineage == currentStateMeta.Lineage
|
if currentStateMeta.Lineage != "" && priorStateFile.Lineage != "" {
|
||||||
if priorStateFile.Serial != currentStateMeta.Serial || !lineageOk {
|
if priorStateFile.Serial != currentStateMeta.Serial || priorStateFile.Lineage != currentStateMeta.Lineage {
|
||||||
diags = diags.Append(tfdiags.Sourceless(
|
diags = diags.Append(tfdiags.Sourceless(
|
||||||
tfdiags.Error,
|
tfdiags.Error,
|
||||||
"Saved plan is stale",
|
"Saved plan is stale",
|
||||||
"The given plan file can no longer be applied because the state was changed by another operation after the plan was created.",
|
"The given plan file can no longer be applied because the state was changed by another operation after the plan was created.",
|
||||||
))
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// The caller already wrote the "current state" here, but we're overriding
|
// The caller already wrote the "current state" here, but we're overriding
|
||||||
|
@ -331,7 +331,7 @@ func TestApply_error(t *testing.T) {
|
|||||||
statePath := testTempFile(t)
|
statePath := testTempFile(t)
|
||||||
|
|
||||||
p := testProvider()
|
p := testProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := cli.NewMockUi()
|
||||||
c := &ApplyCommand{
|
c := &ApplyCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
@ -367,14 +367,29 @@ func TestApply_error(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
p.GetSchemaReturn = &terraform.ProviderSchema{
|
||||||
|
ResourceTypes: map[string]*configschema.Block{
|
||||||
|
"test_instance": {
|
||||||
|
Attributes: map[string]*configschema.Attribute{
|
||||||
|
"id": {Type: cty.String, Optional: true, Computed: true},
|
||||||
|
"ami": {Type: cty.String, Optional: true},
|
||||||
|
"error": {Type: cty.Bool, Optional: true},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
args := []string{
|
args := []string{
|
||||||
"-state", statePath,
|
"-state", statePath,
|
||||||
"-auto-approve",
|
"-auto-approve",
|
||||||
testFixturePath("apply-error"),
|
testFixturePath("apply-error"),
|
||||||
}
|
}
|
||||||
|
if ui.ErrorWriter != nil {
|
||||||
|
t.Logf("stdout:\n%s", ui.OutputWriter.String())
|
||||||
|
t.Logf("stderr:\n%s", ui.ErrorWriter.String())
|
||||||
|
}
|
||||||
if code := c.Run(args); code != 1 {
|
if code := c.Run(args); code != 1 {
|
||||||
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
t.Fatalf("wrong exit code %d; want 1", code)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := os.Stat(statePath); err != nil {
|
if _, err := os.Stat(statePath); err != nil {
|
||||||
@ -521,10 +536,10 @@ func TestApply_plan(t *testing.T) {
|
|||||||
defaultInputReader = new(bytes.Buffer)
|
defaultInputReader = new(bytes.Buffer)
|
||||||
defaultInputWriter = new(bytes.Buffer)
|
defaultInputWriter = new(bytes.Buffer)
|
||||||
|
|
||||||
planPath := testPlanFileNoop(t)
|
planPath := applyFixturePlanFile(t)
|
||||||
statePath := testTempFile(t)
|
statePath := testTempFile(t)
|
||||||
|
|
||||||
p := testProvider()
|
p := applyFixtureProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
c := &ApplyCommand{
|
c := &ApplyCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
@ -552,11 +567,11 @@ func TestApply_plan(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestApply_plan_backup(t *testing.T) {
|
func TestApply_plan_backup(t *testing.T) {
|
||||||
planPath := testPlanFileNoop(t)
|
planPath := applyFixturePlanFile(t)
|
||||||
statePath := testTempFile(t)
|
statePath := testTempFile(t)
|
||||||
backupPath := testTempFile(t)
|
backupPath := testTempFile(t)
|
||||||
|
|
||||||
p := testProvider()
|
p := applyFixtureProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
c := &ApplyCommand{
|
c := &ApplyCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
@ -584,10 +599,10 @@ func TestApply_plan_backup(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestApply_plan_noBackup(t *testing.T) {
|
func TestApply_plan_noBackup(t *testing.T) {
|
||||||
planPath := testPlanFileNoop(t)
|
planPath := applyFixturePlanFile(t)
|
||||||
statePath := testTempFile(t)
|
statePath := testTempFile(t)
|
||||||
|
|
||||||
p := testProvider()
|
p := applyFixtureProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
c := &ApplyCommand{
|
c := &ApplyCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
@ -640,7 +655,28 @@ func TestApply_plan_remoteState(t *testing.T) {
|
|||||||
testStateFileRemote(t, backendState)
|
testStateFileRemote(t, backendState)
|
||||||
|
|
||||||
_, snap := testModuleWithSnapshot(t, "apply")
|
_, snap := testModuleWithSnapshot(t, "apply")
|
||||||
planPath := testPlanFile(t, snap, state, &plans.Plan{})
|
backendConfig := cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"address": cty.StringVal(srv.URL),
|
||||||
|
"update_method": cty.NullVal(cty.String),
|
||||||
|
"lock_address": cty.NullVal(cty.String),
|
||||||
|
"unlock_address": cty.NullVal(cty.String),
|
||||||
|
"lock_method": cty.NullVal(cty.String),
|
||||||
|
"unlock_method": cty.NullVal(cty.String),
|
||||||
|
"username": cty.NullVal(cty.String),
|
||||||
|
"password": cty.NullVal(cty.String),
|
||||||
|
"skip_cert_verification": cty.NullVal(cty.Bool),
|
||||||
|
})
|
||||||
|
backendConfigRaw, err := plans.NewDynamicValue(backendConfig, backendConfig.Type())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
planPath := testPlanFile(t, snap, state, &plans.Plan{
|
||||||
|
Backend: plans.Backend{
|
||||||
|
Type: "http",
|
||||||
|
Config: backendConfigRaw,
|
||||||
|
},
|
||||||
|
Changes: plans.NewChanges(),
|
||||||
|
})
|
||||||
|
|
||||||
p := testProvider()
|
p := testProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
@ -677,7 +713,7 @@ func TestApply_planWithVarFile(t *testing.T) {
|
|||||||
t.Fatalf("err: %s", err)
|
t.Fatalf("err: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
planPath := testPlanFileNoop(t)
|
planPath := applyFixturePlanFile(t)
|
||||||
statePath := testTempFile(t)
|
statePath := testTempFile(t)
|
||||||
|
|
||||||
cwd, err := os.Getwd()
|
cwd, err := os.Getwd()
|
||||||
@ -689,7 +725,7 @@ func TestApply_planWithVarFile(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer os.Chdir(cwd)
|
defer os.Chdir(cwd)
|
||||||
|
|
||||||
p := testProvider()
|
p := applyFixtureProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
c := &ApplyCommand{
|
c := &ApplyCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
@ -717,10 +753,10 @@ func TestApply_planWithVarFile(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestApply_planVars(t *testing.T) {
|
func TestApply_planVars(t *testing.T) {
|
||||||
planPath := testPlanFileNoop(t)
|
planPath := applyFixturePlanFile(t)
|
||||||
statePath := testTempFile(t)
|
statePath := testTempFile(t)
|
||||||
|
|
||||||
p := testProvider()
|
p := applyFixtureProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
c := &ApplyCommand{
|
c := &ApplyCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
@ -747,8 +783,8 @@ func TestApply_planNoModuleFiles(t *testing.T) {
|
|||||||
|
|
||||||
defer testChdir(t, td)()
|
defer testChdir(t, td)()
|
||||||
|
|
||||||
p := testProvider()
|
p := applyFixtureProvider()
|
||||||
planFile := testPlanFileNoop(t)
|
planPath := applyFixturePlanFile(t)
|
||||||
|
|
||||||
apply := &ApplyCommand{
|
apply := &ApplyCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
@ -757,7 +793,7 @@ func TestApply_planNoModuleFiles(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
args := []string{
|
args := []string{
|
||||||
planFile,
|
planPath,
|
||||||
}
|
}
|
||||||
apply.Run(args)
|
apply.Run(args)
|
||||||
if p.ValidateProviderConfigCalled {
|
if p.ValidateProviderConfigCalled {
|
||||||
@ -1592,6 +1628,45 @@ func applyFixtureProvider() *terraform.MockProvider {
|
|||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// applyFixturePlanFile creates a plan file at a temporary location containing
|
||||||
|
// a single change to create the test_instance.foo that is included in the
|
||||||
|
// "apply" test fixture, returning the location of that plan file.
|
||||||
|
func applyFixturePlanFile(t *testing.T) string {
|
||||||
|
_, snap := testModuleWithSnapshot(t, "apply")
|
||||||
|
plannedVal := cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"id": cty.UnknownVal(cty.String),
|
||||||
|
"ami": cty.StringVal("bar"),
|
||||||
|
})
|
||||||
|
priorValRaw, err := plans.NewDynamicValue(cty.NullVal(plannedVal.Type()), plannedVal.Type())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
plannedValRaw, err := plans.NewDynamicValue(plannedVal, plannedVal.Type())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
plan := testPlan(t)
|
||||||
|
plan.Changes.SyncWrapper().AppendResourceInstanceChange(&plans.ResourceInstanceChangeSrc{
|
||||||
|
Addr: addrs.Resource{
|
||||||
|
Mode: addrs.ManagedResourceMode,
|
||||||
|
Type: "test_instance",
|
||||||
|
Name: "foo",
|
||||||
|
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
|
||||||
|
ProviderAddr: addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance),
|
||||||
|
ChangeSrc: plans.ChangeSrc{
|
||||||
|
Action: plans.Create,
|
||||||
|
Before: priorValRaw,
|
||||||
|
After: plannedValRaw,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return testPlanFile(
|
||||||
|
t,
|
||||||
|
snap,
|
||||||
|
states.NewState(),
|
||||||
|
plan,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const applyVarFile = `
|
const applyVarFile = `
|
||||||
foo = "bar"
|
foo = "bar"
|
||||||
`
|
`
|
||||||
|
@ -182,7 +182,7 @@ func testPlanFile(t *testing.T, configSnap *configload.Snapshot, state *states.S
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
stateFile := &statefile.File{
|
stateFile := &statefile.File{
|
||||||
Lineage: "command.testPlanFile",
|
Lineage: "",
|
||||||
State: state,
|
State: state,
|
||||||
TerraformVersion: version.SemVer,
|
TerraformVersion: version.SemVer,
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/hashicorp/hcl2/hcl"
|
"github.com/hashicorp/hcl2/hcl"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/addrs"
|
||||||
"github.com/hashicorp/terraform/configs"
|
"github.com/hashicorp/terraform/configs"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -77,6 +78,18 @@ type Snapshot struct {
|
|||||||
Modules map[string]*SnapshotModule
|
Modules map[string]*SnapshotModule
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewEmptySnapshot constructs and returns a snapshot containing only an empty
|
||||||
|
// root module. This is not useful for anything except placeholders in tests.
|
||||||
|
func NewEmptySnapshot() *Snapshot {
|
||||||
|
return &Snapshot{
|
||||||
|
Modules: map[string]*SnapshotModule{
|
||||||
|
manifestKey(addrs.RootModule): &SnapshotModule{
|
||||||
|
Files: map[string][]byte{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// SnapshotModule represents a single module within a Snapshot.
|
// SnapshotModule represents a single module within a Snapshot.
|
||||||
type SnapshotModule struct {
|
type SnapshotModule struct {
|
||||||
// Dir is the path, relative to the root directory given when the
|
// Dir is the path, relative to the root directory given when the
|
||||||
|
Loading…
Reference in New Issue
Block a user