command: recompute config hash with ConfigFile set
Fixes #12749 If we merge in an extra partial config we need to recompute the hash to compare with the old value to detect that change. This hash needs to NOT be stored and just used as a temporary. We want to keep the original hash in the state so that we don't detect a change from the config (since the config will always be partial).
This commit is contained in:
parent
ead7a3758b
commit
81639480fb
|
@ -321,6 +321,38 @@ func TestInit_backendConfigFile(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInit_backendConfigFileChange(t *testing.T) {
|
||||||
|
// Create a temporary working directory that is empty
|
||||||
|
td := tempDir(t)
|
||||||
|
copy.CopyDir(testFixturePath("init-backend-config-file-change"), td)
|
||||||
|
defer os.RemoveAll(td)
|
||||||
|
defer testChdir(t, td)()
|
||||||
|
|
||||||
|
// Ask input
|
||||||
|
defer testInputMap(t, map[string]string{
|
||||||
|
"backend-migrate-to-new": "no",
|
||||||
|
})()
|
||||||
|
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
c := &InitCommand{
|
||||||
|
Meta: Meta{
|
||||||
|
ContextOpts: testCtxConfig(testProvider()),
|
||||||
|
Ui: ui,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{"-backend-config", "input.config"}
|
||||||
|
if code := c.Run(args); code != 0 {
|
||||||
|
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read our saved backend config and verify we have our settings
|
||||||
|
state := testStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename))
|
||||||
|
if v := state.Backend.Config["path"]; v != "hello" {
|
||||||
|
t.Fatalf("bad: %#v", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestInit_copyBackendDst(t *testing.T) {
|
func TestInit_copyBackendDst(t *testing.T) {
|
||||||
// Create a temporary working directory that is empty
|
// Create a temporary working directory that is empty
|
||||||
td := tempDir(t)
|
td := tempDir(t)
|
||||||
|
|
|
@ -302,6 +302,16 @@ func (m *Meta) backendFromConfig(opts *BackendOpts) (backend.Backend, error) {
|
||||||
return nil, fmt.Errorf("Error loading backend config: %s", err)
|
return nil, fmt.Errorf("Error loading backend config: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cHash defaults to zero unless c is set
|
||||||
|
var cHash uint64
|
||||||
|
if c != nil {
|
||||||
|
// We need to rehash to get the value since we may have merged the
|
||||||
|
// config with an extra ConfigFile. We don't do this when merging
|
||||||
|
// because we do want the ORIGINAL value on c so that we store
|
||||||
|
// that to not detect drift. This is covered in tests.
|
||||||
|
cHash = c.Rehash()
|
||||||
|
}
|
||||||
|
|
||||||
// Get the path to where we store a local cache of backend configuration
|
// Get the path to where we store a local cache of backend configuration
|
||||||
// if we're using a remote backend. This may not yet exist which means
|
// if we're using a remote backend. This may not yet exist which means
|
||||||
// we haven't used a non-local backend before. That is okay.
|
// we haven't used a non-local backend before. That is okay.
|
||||||
|
@ -384,7 +394,7 @@ func (m *Meta) backendFromConfig(opts *BackendOpts) (backend.Backend, error) {
|
||||||
case c != nil && s.Remote.Empty() && !s.Backend.Empty():
|
case c != nil && s.Remote.Empty() && !s.Backend.Empty():
|
||||||
// If our configuration is the same, then we're just initializing
|
// If our configuration is the same, then we're just initializing
|
||||||
// a previously configured remote backend.
|
// a previously configured remote backend.
|
||||||
if !s.Backend.Empty() && s.Backend.Hash == c.Hash {
|
if !s.Backend.Empty() && s.Backend.Hash == cHash {
|
||||||
return m.backend_C_r_S_unchanged(c, sMgr)
|
return m.backend_C_r_S_unchanged(c, sMgr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,7 +408,7 @@ func (m *Meta) backendFromConfig(opts *BackendOpts) (backend.Backend, error) {
|
||||||
|
|
||||||
log.Printf(
|
log.Printf(
|
||||||
"[WARN] command: backend config change! saved: %d, new: %d",
|
"[WARN] command: backend config change! saved: %d, new: %d",
|
||||||
s.Backend.Hash, c.Hash)
|
s.Backend.Hash, cHash)
|
||||||
return m.backend_C_r_S_changed(c, sMgr, true)
|
return m.backend_C_r_S_changed(c, sMgr, true)
|
||||||
|
|
||||||
// Configuring a backend for the first time while having legacy
|
// Configuring a backend for the first time while having legacy
|
||||||
|
@ -420,7 +430,7 @@ func (m *Meta) backendFromConfig(opts *BackendOpts) (backend.Backend, error) {
|
||||||
case c != nil && !s.Remote.Empty() && !s.Backend.Empty():
|
case c != nil && !s.Remote.Empty() && !s.Backend.Empty():
|
||||||
// If the hashes are the same, we have a legacy remote state with
|
// If the hashes are the same, we have a legacy remote state with
|
||||||
// an unchanged stored backend state.
|
// an unchanged stored backend state.
|
||||||
if s.Backend.Hash == c.Hash {
|
if s.Backend.Hash == cHash {
|
||||||
if !opts.Init {
|
if !opts.Init {
|
||||||
initReason := fmt.Sprintf(
|
initReason := fmt.Sprintf(
|
||||||
"Legacy remote state found with configured backend %q",
|
"Legacy remote state found with configured backend %q",
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"serial": 0,
|
||||||
|
"lineage": "666f9301-7e65-4b19-ae23-71184bb19b03",
|
||||||
|
"backend": {
|
||||||
|
"type": "local",
|
||||||
|
"config": {
|
||||||
|
"path": "local-state.tfstate"
|
||||||
|
},
|
||||||
|
"hash": 9073424445967744180
|
||||||
|
},
|
||||||
|
"modules": [
|
||||||
|
{
|
||||||
|
"path": [
|
||||||
|
"root"
|
||||||
|
],
|
||||||
|
"outputs": {},
|
||||||
|
"resources": {},
|
||||||
|
"depends_on": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
path = "hello"
|
|
@ -0,0 +1,5 @@
|
||||||
|
terraform {
|
||||||
|
backend "local" {
|
||||||
|
path = "local-state.tfstate"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue