Merge pull request #28864 from hashicorp/alisdair/fix-remote-backend-multi-workspace-state-migration

Fix remote backend multi workspace state migration
This commit is contained in:
Alisdair McDiarmid 2021-06-08 10:10:58 -04:00 committed by GitHub
commit 24ace6ae7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 36 deletions

View File

@ -49,6 +49,7 @@ func (c *InitCommand) Run(args []string) int {
cmdFlags.BoolVar(&flagUpgrade, "upgrade", false, "")
cmdFlags.Var(&flagPluginPath, "plugin-dir", "plugin directory")
cmdFlags.StringVar(&flagLockfile, "lockfile", "", "Set a dependency lockfile mode")
cmdFlags.BoolVar(&c.Meta.ignoreRemoteVersion, "ignore-remote-version", false, "continue even if remote and local Terraform versions are incompatible")
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
if err := cmdFlags.Parse(args); err != nil {
return 1
@ -962,46 +963,49 @@ Usage: terraform [global options] init [options]
Options:
-backend=true Configure the backend for this configuration.
-backend=true Configure the backend for this configuration.
-backend-config=path This can be either a path to an HCL file with key/value
assignments (same format as terraform.tfvars) or a
'key=value' format. This is merged with what is in the
configuration file. This can be specified multiple
times. The backend type must be in the configuration
itself.
-backend-config=path This can be either a path to an HCL file with key/value
assignments (same format as terraform.tfvars) or a
'key=value' format. This is merged with what is in the
configuration file. This can be specified multiple
times. The backend type must be in the configuration
itself.
-force-copy Suppress prompts about copying state data. This is
equivalent to providing a "yes" to all confirmation
prompts.
-force-copy Suppress prompts about copying state data. This is
equivalent to providing a "yes" to all confirmation
prompts.
-from-module=SOURCE Copy the contents of the given module into the target
directory before initialization.
-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=true Download any modules for this configuration.
-input=true Ask for input if necessary. If false, will error if
input was required.
-input=true Ask for input if necessary. If false, will error if
input was required.
-no-color If specified, output won't contain any color.
-no-color If specified, output won't contain any color.
-plugin-dir Directory containing plugin binaries. This overrides all
default search paths for plugins, and prevents the
automatic installation of plugins. This flag can be used
multiple times.
-plugin-dir Directory containing plugin binaries. This overrides all
default search paths for plugins, and prevents the
automatic installation of plugins. This flag can be used
multiple times.
-reconfigure Reconfigure the backend, ignoring any saved
configuration.
-reconfigure Reconfigure the backend, ignoring any saved
configuration.
-migrate-state Reconfigure the backend, and attempt to migrate any
existing state.
-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=false If installing modules (-get) or plugins, ignore
previously-downloaded objects and install the
latest version allowed within configured constraints.
-lockfile=MODE Set a dependency lockfile mode.
Currently only "readonly" is valid.
-lockfile=MODE Set a dependency lockfile mode.
Currently only "readonly" is valid.
-ignore-remote-version A rare option used for the remote backend only. See
the remote backend documentation for more information.
`
return strings.TrimSpace(helpText)

View File

@ -57,7 +57,7 @@ func (m *Meta) backendMigrateState(opts *backendMigrateOpts) error {
errMigrateLoadStates), opts.OneType, err)
}
_, err = opts.Two.Workspaces()
twoWorkspaces, err := opts.Two.Workspaces()
if err == backend.ErrWorkspacesNotSupported {
twoSingle = true
err = nil
@ -77,12 +77,14 @@ func (m *Meta) backendMigrateState(opts *backendMigrateOpts) error {
// as we are migrating away and will not break a remote workspace.
m.ignoreRemoteBackendVersionConflict(opts.One)
// Check the remote Terraform version for the state destination backend. If
// it's a Terraform Cloud remote backend, we want to ensure that we don't
// break the workspace by uploading an incompatible state file.
diags := m.remoteBackendVersionCheck(opts.Two, opts.twoEnv)
if diags.HasErrors() {
return diags.Err()
for _, twoWorkspace := range twoWorkspaces {
// Check the remote Terraform version for the state destination backend. If
// it's a Terraform Cloud remote backend, we want to ensure that we don't
// break the workspace by uploading an incompatible state file.
diags := m.remoteBackendVersionCheck(opts.Two, twoWorkspace)
if diags.HasErrors() {
return diags.Err()
}
}
// Determine migration behavior based on whether the source/destination