Merge pull request #12939 from hashicorp/jbardin/GH-12921
add `-force-copy` option to init command
This commit is contained in:
commit
ddb9c51481
|
@ -21,11 +21,14 @@ type InitCommand struct {
|
||||||
func (c *InitCommand) Run(args []string) int {
|
func (c *InitCommand) Run(args []string) int {
|
||||||
var flagBackend, flagGet bool
|
var flagBackend, flagGet bool
|
||||||
var flagConfigExtra map[string]interface{}
|
var flagConfigExtra map[string]interface{}
|
||||||
|
|
||||||
args = c.Meta.process(args, false)
|
args = c.Meta.process(args, false)
|
||||||
cmdFlags := c.flagSet("init")
|
cmdFlags := c.flagSet("init")
|
||||||
cmdFlags.BoolVar(&flagBackend, "backend", true, "")
|
cmdFlags.BoolVar(&flagBackend, "backend", true, "")
|
||||||
cmdFlags.Var((*variables.FlagAny)(&flagConfigExtra), "backend-config", "")
|
cmdFlags.Var((*variables.FlagAny)(&flagConfigExtra), "backend-config", "")
|
||||||
cmdFlags.BoolVar(&flagGet, "get", true, "")
|
cmdFlags.BoolVar(&flagGet, "get", true, "")
|
||||||
|
cmdFlags.BoolVar(&c.forceInitCopy, "force-copy", false, "suppress prompts about copying state data")
|
||||||
|
|
||||||
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||||
if err := cmdFlags.Parse(args); err != nil {
|
if err := cmdFlags.Parse(args); err != nil {
|
||||||
return 1
|
return 1
|
||||||
|
@ -225,6 +228,10 @@ Options:
|
||||||
|
|
||||||
-no-color If specified, output won't contain any color.
|
-no-color If specified, output won't contain any color.
|
||||||
|
|
||||||
|
-force-copy Suppress prompts about copying state data. This is
|
||||||
|
equivalent to providing a "yes" to all confirmation
|
||||||
|
prompts.
|
||||||
|
|
||||||
`
|
`
|
||||||
return strings.TrimSpace(helpText)
|
return strings.TrimSpace(helpText)
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,9 +270,6 @@ func TestInit_backendUnset(t *testing.T) {
|
||||||
t.Fatalf("err: %s", err)
|
t.Fatalf("err: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run it again
|
|
||||||
defer testInteractiveInput(t, []string{"yes", "yes"})()
|
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
c := &InitCommand{
|
c := &InitCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
|
@ -281,7 +278,7 @@ func TestInit_backendUnset(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
args := []string{}
|
args := []string{"-force-copy"}
|
||||||
if code := c.Run(args); code != 0 {
|
if code := c.Run(args); code != 0 {
|
||||||
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
|
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,14 +87,18 @@ type Meta struct {
|
||||||
//
|
//
|
||||||
// provider is to specify specific resource providers
|
// provider is to specify specific resource providers
|
||||||
//
|
//
|
||||||
// lockState is set to false to disable state locking
|
// stateLock is set to false to disable state locking
|
||||||
statePath string
|
//
|
||||||
stateOutPath string
|
// forceInitCopy suppresses confirmation for copying state data during
|
||||||
backupPath string
|
// init.
|
||||||
parallelism int
|
statePath string
|
||||||
shadow bool
|
stateOutPath string
|
||||||
provider string
|
backupPath string
|
||||||
stateLock bool
|
parallelism int
|
||||||
|
shadow bool
|
||||||
|
provider string
|
||||||
|
stateLock bool
|
||||||
|
forceInitCopy bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// initStatePaths is used to initialize the default values for
|
// initStatePaths is used to initialize the default values for
|
||||||
|
|
|
@ -684,16 +684,20 @@ func (m *Meta) backend_c_r_S(
|
||||||
// Get the backend type for output
|
// Get the backend type for output
|
||||||
backendType := s.Backend.Type
|
backendType := s.Backend.Type
|
||||||
|
|
||||||
// Confirm with the user that the copy should occur
|
copy := m.forceInitCopy
|
||||||
copy, err := m.confirm(&terraform.InputOpts{
|
if !copy {
|
||||||
Id: "backend-migrate-to-local",
|
var err error
|
||||||
Query: fmt.Sprintf("Do you want to copy the state from %q?", s.Backend.Type),
|
// Confirm with the user that the copy should occur
|
||||||
Description: fmt.Sprintf(
|
copy, err = m.confirm(&terraform.InputOpts{
|
||||||
strings.TrimSpace(inputBackendMigrateLocal), s.Backend.Type),
|
Id: "backend-migrate-to-local",
|
||||||
})
|
Query: fmt.Sprintf("Do you want to copy the state from %q?", s.Backend.Type),
|
||||||
if err != nil {
|
Description: fmt.Sprintf(
|
||||||
return nil, fmt.Errorf(
|
strings.TrimSpace(inputBackendMigrateLocal), s.Backend.Type),
|
||||||
"Error asking for state copy action: %s", err)
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"Error asking for state copy action: %s", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're copying, perform the migration
|
// If we're copying, perform the migration
|
||||||
|
@ -805,16 +809,19 @@ func (m *Meta) backend_c_R_S(
|
||||||
s := sMgr.State()
|
s := sMgr.State()
|
||||||
|
|
||||||
// Ask the user if they want to migrate their existing remote state
|
// Ask the user if they want to migrate their existing remote state
|
||||||
copy, err := m.confirm(&terraform.InputOpts{
|
copy := m.forceInitCopy
|
||||||
Id: "backend-migrate-to-new",
|
if !copy {
|
||||||
Query: fmt.Sprintf(
|
copy, err = m.confirm(&terraform.InputOpts{
|
||||||
"Do you want to copy the legacy remote state from %q?",
|
Id: "backend-migrate-to-new",
|
||||||
s.Remote.Type),
|
Query: fmt.Sprintf(
|
||||||
Description: strings.TrimSpace(inputBackendMigrateLegacyLocal),
|
"Do you want to copy the legacy remote state from %q?",
|
||||||
})
|
s.Remote.Type),
|
||||||
if err != nil {
|
Description: strings.TrimSpace(inputBackendMigrateLegacyLocal),
|
||||||
return nil, fmt.Errorf(
|
})
|
||||||
"Error asking for state copy action: %s", err)
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"Error asking for state copy action: %s", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the user wants a copy, copy!
|
// If the user wants a copy, copy!
|
||||||
|
@ -898,16 +905,19 @@ func (m *Meta) backend_C_R_s(
|
||||||
|
|
||||||
// Finally, ask the user if they want to copy the state from
|
// Finally, ask the user if they want to copy the state from
|
||||||
// their old remote state location.
|
// their old remote state location.
|
||||||
copy, err := m.confirm(&terraform.InputOpts{
|
copy := m.forceInitCopy
|
||||||
Id: "backend-migrate-to-new",
|
if !copy {
|
||||||
Query: fmt.Sprintf(
|
copy, err = m.confirm(&terraform.InputOpts{
|
||||||
"Do you want to copy the legacy remote state from %q?",
|
Id: "backend-migrate-to-new",
|
||||||
s.Remote.Type),
|
Query: fmt.Sprintf(
|
||||||
Description: strings.TrimSpace(inputBackendMigrateLegacy),
|
"Do you want to copy the legacy remote state from %q?",
|
||||||
})
|
s.Remote.Type),
|
||||||
if err != nil {
|
Description: strings.TrimSpace(inputBackendMigrateLegacy),
|
||||||
return nil, fmt.Errorf(
|
})
|
||||||
"Error asking for state copy action: %s", err)
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"Error asking for state copy action: %s", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the user wants a copy, copy!
|
// If the user wants a copy, copy!
|
||||||
|
@ -1055,14 +1065,17 @@ func (m *Meta) backend_C_r_S_changed(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check with the user if we want to migrate state
|
// Check with the user if we want to migrate state
|
||||||
copy, err := m.confirm(&terraform.InputOpts{
|
copy := m.forceInitCopy
|
||||||
Id: "backend-migrate-to-new",
|
if !copy {
|
||||||
Query: fmt.Sprintf("Do you want to copy the state from %q?", c.Type),
|
copy, err = m.confirm(&terraform.InputOpts{
|
||||||
Description: strings.TrimSpace(fmt.Sprintf(inputBackendMigrateChange, c.Type, s.Backend.Type)),
|
Id: "backend-migrate-to-new",
|
||||||
})
|
Query: fmt.Sprintf("Do you want to copy the state from %q?", c.Type),
|
||||||
if err != nil {
|
Description: strings.TrimSpace(fmt.Sprintf(inputBackendMigrateChange, c.Type, s.Backend.Type)),
|
||||||
return nil, fmt.Errorf(
|
})
|
||||||
"Error asking for state copy action: %s", err)
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"Error asking for state copy action: %s", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are, then we need to initialize the old backend and
|
// If we are, then we need to initialize the old backend and
|
||||||
|
@ -1198,16 +1211,19 @@ func (m *Meta) backend_C_R_S_unchanged(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ask if the user wants to move their legacy remote state
|
// Ask if the user wants to move their legacy remote state
|
||||||
copy, err := m.confirm(&terraform.InputOpts{
|
copy := m.forceInitCopy
|
||||||
Id: "backend-migrate-to-new",
|
if !copy {
|
||||||
Query: fmt.Sprintf(
|
copy, err = m.confirm(&terraform.InputOpts{
|
||||||
"Do you want to copy the legacy remote state from %q?",
|
Id: "backend-migrate-to-new",
|
||||||
s.Remote.Type),
|
Query: fmt.Sprintf(
|
||||||
Description: strings.TrimSpace(inputBackendMigrateLegacy),
|
"Do you want to copy the legacy remote state from %q?",
|
||||||
})
|
s.Remote.Type),
|
||||||
if err != nil {
|
Description: strings.TrimSpace(inputBackendMigrateLegacy),
|
||||||
return nil, fmt.Errorf(
|
})
|
||||||
"Error asking for state copy action: %s", err)
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"Error asking for state copy action: %s", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the user wants a copy, copy!
|
// If the user wants a copy, copy!
|
||||||
|
|
|
@ -162,21 +162,26 @@ func (m *Meta) backendMigrateState_S_S(opts *backendMigrateOpts) error {
|
||||||
func (m *Meta) backendMigrateState_S_s(opts *backendMigrateOpts) error {
|
func (m *Meta) backendMigrateState_S_s(opts *backendMigrateOpts) error {
|
||||||
currentEnv := m.Env()
|
currentEnv := m.Env()
|
||||||
|
|
||||||
// Ask the user if they want to migrate their existing remote state
|
migrate := m.forceInitCopy
|
||||||
migrate, err := m.confirm(&terraform.InputOpts{
|
if !migrate {
|
||||||
Id: "backend-migrate-multistate-to-single",
|
var err error
|
||||||
Query: fmt.Sprintf(
|
// Ask the user if they want to migrate their existing remote state
|
||||||
"Destination state %q doesn't support environments (named states).\n"+
|
migrate, err = m.confirm(&terraform.InputOpts{
|
||||||
"Do you want to copy only your current environment?",
|
Id: "backend-migrate-multistate-to-single",
|
||||||
opts.TwoType),
|
Query: fmt.Sprintf(
|
||||||
Description: fmt.Sprintf(
|
"Destination state %q doesn't support environments (named states).\n"+
|
||||||
strings.TrimSpace(inputBackendMigrateMultiToSingle),
|
"Do you want to copy only your current environment?",
|
||||||
opts.OneType, opts.TwoType, currentEnv),
|
opts.TwoType),
|
||||||
})
|
Description: fmt.Sprintf(
|
||||||
if err != nil {
|
strings.TrimSpace(inputBackendMigrateMultiToSingle),
|
||||||
return fmt.Errorf(
|
opts.OneType, opts.TwoType, currentEnv),
|
||||||
"Error asking for state migration action: %s", err)
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"Error asking for state migration action: %s", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !migrate {
|
if !migrate {
|
||||||
return fmt.Errorf("Migration aborted by user.")
|
return fmt.Errorf("Migration aborted by user.")
|
||||||
}
|
}
|
||||||
|
@ -295,6 +300,10 @@ func (m *Meta) backendMigrateState_s_s(opts *backendMigrateOpts) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Meta) backendMigrateEmptyConfirm(one, two state.State, opts *backendMigrateOpts) (bool, error) {
|
func (m *Meta) backendMigrateEmptyConfirm(one, two state.State, opts *backendMigrateOpts) (bool, error) {
|
||||||
|
if m.forceInitCopy {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
inputOpts := &terraform.InputOpts{
|
inputOpts := &terraform.InputOpts{
|
||||||
Id: "backend-migrate-copy-to-empty",
|
Id: "backend-migrate-copy-to-empty",
|
||||||
Query: fmt.Sprintf(
|
Query: fmt.Sprintf(
|
||||||
|
@ -357,6 +366,10 @@ func (m *Meta) backendMigrateNonEmptyConfirm(
|
||||||
return false, fmt.Errorf("Error saving temporary state: %s", err)
|
return false, fmt.Errorf("Error saving temporary state: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if m.forceInitCopy {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Ask for confirmation
|
// Ask for confirmation
|
||||||
inputOpts := &terraform.InputOpts{
|
inputOpts := &terraform.InputOpts{
|
||||||
Id: "backend-migrate-to-backend",
|
Id: "backend-migrate-to-backend",
|
||||||
|
|
|
@ -480,11 +480,10 @@ func TestMetaBackend_configureNewWithStateExisting(t *testing.T) {
|
||||||
defer os.RemoveAll(td)
|
defer os.RemoveAll(td)
|
||||||
defer testChdir(t, td)()
|
defer testChdir(t, td)()
|
||||||
|
|
||||||
// Ask input
|
|
||||||
defer testInteractiveInput(t, []string{"yes"})()
|
|
||||||
|
|
||||||
// Setup the meta
|
// Setup the meta
|
||||||
m := testMetaBackend(t, nil)
|
m := testMetaBackend(t, nil)
|
||||||
|
// suppress input
|
||||||
|
m.forceInitCopy = true
|
||||||
|
|
||||||
// Get the backend
|
// Get the backend
|
||||||
b, err := m.Backend(&BackendOpts{Init: true})
|
b, err := m.Backend(&BackendOpts{Init: true})
|
||||||
|
@ -722,12 +721,12 @@ func TestMetaBackend_configureNewLegacyCopy(t *testing.T) {
|
||||||
defer os.RemoveAll(td)
|
defer os.RemoveAll(td)
|
||||||
defer testChdir(t, td)()
|
defer testChdir(t, td)()
|
||||||
|
|
||||||
// Ask input
|
|
||||||
defer testInteractiveInput(t, []string{"yes", "yes"})()
|
|
||||||
|
|
||||||
// Setup the meta
|
// Setup the meta
|
||||||
m := testMetaBackend(t, nil)
|
m := testMetaBackend(t, nil)
|
||||||
|
|
||||||
|
// suppress input
|
||||||
|
m.forceInitCopy = true
|
||||||
|
|
||||||
// Get the backend
|
// Get the backend
|
||||||
b, err := m.Backend(&BackendOpts{Init: true})
|
b, err := m.Backend(&BackendOpts{Init: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1593,11 +1592,9 @@ func TestMetaBackend_configuredUnchangedLegacyCopy(t *testing.T) {
|
||||||
defer os.RemoveAll(td)
|
defer os.RemoveAll(td)
|
||||||
defer testChdir(t, td)()
|
defer testChdir(t, td)()
|
||||||
|
|
||||||
// Ask input
|
|
||||||
defer testInteractiveInput(t, []string{"yes", "yes"})()
|
|
||||||
|
|
||||||
// Setup the meta
|
// Setup the meta
|
||||||
m := testMetaBackend(t, nil)
|
m := testMetaBackend(t, nil)
|
||||||
|
m.forceInitCopy = true
|
||||||
|
|
||||||
// Get the backend
|
// Get the backend
|
||||||
b, err := m.Backend(&BackendOpts{Init: true})
|
b, err := m.Backend(&BackendOpts{Init: true})
|
||||||
|
|
Loading…
Reference in New Issue