cli: Restore -lock and -lock-timeout init flags

The -lock and -lock-timeout flags were removed prior to the release of
1.0 as they were thought to have no effect. This is not true in the case
of state migrations when changing backends. This commit restores these
flags, and adds test coverage for locking during backend state
migration.

Also update the help output describing other boolean flags, showing the
argument as the user would type it rather than the default behavior.
This commit is contained in:
Alisdair McDiarmid 2021-10-18 14:41:04 -04:00
parent 7d3074df46
commit c587384dff
5 changed files with 102 additions and 7 deletions

View File

@ -44,6 +44,8 @@ func (c *InitCommand) Run(args []string) int {
cmdFlags.StringVar(&flagFromModule, "from-module", "", "copy the source of the given module into the directory before init")
cmdFlags.BoolVar(&flagGet, "get", true, "")
cmdFlags.BoolVar(&c.forceInitCopy, "force-copy", false, "suppress prompts about copying state data")
cmdFlags.BoolVar(&c.Meta.stateLock, "lock", true, "lock state")
cmdFlags.DurationVar(&c.Meta.stateLockTimeout, "lock-timeout", 0, "lock timeout")
cmdFlags.BoolVar(&c.reconfigure, "reconfigure", false, "reconfigure")
cmdFlags.BoolVar(&c.migrateState, "migrate-state", false, "migrate state")
cmdFlags.BoolVar(&flagUpgrade, "upgrade", false, "")
@ -932,6 +934,8 @@ func (c *InitCommand) AutocompleteFlags() complete.Flags {
"-from-module": completePredictModuleSource,
"-get": completePredictBoolean,
"-input": completePredictBoolean,
"-lock": completePredictBoolean,
"-lock-timeout": complete.PredictAnything,
"-no-color": complete.PredictNothing,
"-plugin-dir": complete.PredictDirs(""),
"-reconfigure": complete.PredictNothing,
@ -959,7 +963,8 @@ Usage: terraform [global options] init [options]
Options:
-backend=true Configure the backend for this configuration.
-backend=false Disable backend initialization for this configuration
and use the previously initialized backend instead.
-backend-config=path This can be either a path to an HCL file with key/value
assignments (same format as terraform.tfvars) or a
@ -975,10 +980,17 @@ Options:
-from-module=SOURCE Copy the contents of the given module into the target
directory before initialization.
-get=true Download any modules for this configuration.
-get=false Disable downloading modules for this configuration.
-input=true Ask for input if necessary. If false, will error if
input was required.
-input=false Disable prompting for missing backend configuration
values. This will result in an error if the backend
configuration is not fully specified.
-lock=false Don't hold a state lock during backend migration.
This is dangerous if others might concurrently run
commands against the same workspace.
-lock-timeout=0s Duration to retry a state lock.
-no-color If specified, output won't contain any color.
@ -993,9 +1005,10 @@ Options:
-migrate-state Reconfigure the backend, and attempt to migrate any
existing state.
-upgrade=false If installing modules (-get) or plugins, ignore
previously-downloaded objects and install the
latest version allowed within configured constraints.
-upgrade Install the latest module and provider versions
allowed within configured constraints, overriding the
default behavior of selecting exactly the version
recorded in the dependency lockfile.
-lockfile=MODE Set a dependency lockfile mode.
Currently only "readonly" is valid.

View File

@ -562,6 +562,60 @@ func TestInit_backendConfigFileChange(t *testing.T) {
}
}
func TestInit_backendMigrateWhileLocked(t *testing.T) {
// Create a temporary working directory that is empty
td := tempDir(t)
testCopyDir(t, testFixturePath("init-backend-migrate-while-locked"), td)
defer os.RemoveAll(td)
defer testChdir(t, td)()
providerSource, close := newMockProviderSource(t, map[string][]string{
"hashicorp/test": {"1.2.3"},
})
defer close()
ui := new(cli.MockUi)
view, _ := testView(t)
c := &InitCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(testProvider()),
ProviderSource: providerSource,
Ui: ui,
View: view,
},
}
// Create some state, so the backend has something to migrate from
f, err := os.Create("local-state.tfstate")
if err != nil {
t.Fatalf("err: %s", err)
}
err = writeStateForTesting(testState(), f)
f.Close()
if err != nil {
t.Fatalf("err: %s", err)
}
// Lock the source state
unlock, err := testLockState(testDataDir, "local-state.tfstate")
if err != nil {
t.Fatal(err)
}
defer unlock()
// Attempt to migrate
args := []string{"-backend-config", "input.config", "-migrate-state", "-force-copy"}
if code := c.Run(args); code == 0 {
t.Fatalf("expected nonzero exit code: %s", ui.OutputWriter.String())
}
// Disabling locking should work
args = []string{"-backend-config", "input.config", "-migrate-state", "-force-copy", "-lock=false"}
if code := c.Run(args); code != 0 {
t.Fatalf("expected zero exit code, got %d: %s", code, ui.ErrorWriter.String())
}
}
func TestInit_backendConfigKV(t *testing.T) {
// Create a temporary working directory that is empty
td := tempDir(t)

View File

@ -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": []
}
]
}

View File

@ -0,0 +1 @@
path = "hello"

View File

@ -0,0 +1,5 @@
terraform {
backend "local" {
path = "local-state.tfstate"
}
}