mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-28 18:01:01 -06:00
command/taint: -allow-missing
This commit is contained in:
parent
d43c88f5f3
commit
d411e2939f
@ -15,8 +15,10 @@ type TaintCommand struct {
|
|||||||
func (c *TaintCommand) Run(args []string) int {
|
func (c *TaintCommand) Run(args []string) int {
|
||||||
args = c.Meta.process(args, false)
|
args = c.Meta.process(args, false)
|
||||||
|
|
||||||
|
var allowMissing bool
|
||||||
var module string
|
var module string
|
||||||
cmdFlags := c.Meta.flagSet("taint")
|
cmdFlags := c.Meta.flagSet("taint")
|
||||||
|
cmdFlags.BoolVar(&allowMissing, "allow-missing", false, "module")
|
||||||
cmdFlags.StringVar(&module, "module", "", "module")
|
cmdFlags.StringVar(&module, "module", "", "module")
|
||||||
cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path")
|
cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path")
|
||||||
cmdFlags.StringVar(&c.Meta.stateOutPath, "state-out", "", "path")
|
cmdFlags.StringVar(&c.Meta.stateOutPath, "state-out", "", "path")
|
||||||
@ -33,7 +35,13 @@ func (c *TaintCommand) Run(args []string) int {
|
|||||||
cmdFlags.Usage()
|
cmdFlags.Usage()
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
name := args[0]
|
name := args[0]
|
||||||
|
if module == "" {
|
||||||
|
module = "root"
|
||||||
|
} else {
|
||||||
|
module = "root." + module
|
||||||
|
}
|
||||||
|
|
||||||
// Get the state that we'll be modifying
|
// Get the state that we'll be modifying
|
||||||
state, err := c.State()
|
state, err := c.State()
|
||||||
@ -45,6 +53,10 @@ func (c *TaintCommand) Run(args []string) int {
|
|||||||
// Get the actual state structure
|
// Get the actual state structure
|
||||||
s := state.State()
|
s := state.State()
|
||||||
if s.Empty() {
|
if s.Empty() {
|
||||||
|
if allowMissing {
|
||||||
|
return c.allowMissingExit(name, module)
|
||||||
|
}
|
||||||
|
|
||||||
c.Ui.Error(fmt.Sprintf(
|
c.Ui.Error(fmt.Sprintf(
|
||||||
"The state is empty. The most common reason for this is that\n" +
|
"The state is empty. The most common reason for this is that\n" +
|
||||||
"an invalid state file path was given or Terraform has never\n " +
|
"an invalid state file path was given or Terraform has never\n " +
|
||||||
@ -54,14 +66,13 @@ func (c *TaintCommand) Run(args []string) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the proper module we want to taint
|
// Get the proper module we want to taint
|
||||||
if module == "" {
|
|
||||||
module = "root"
|
|
||||||
} else {
|
|
||||||
module = "root." + module
|
|
||||||
}
|
|
||||||
modPath := strings.Split(module, ".")
|
modPath := strings.Split(module, ".")
|
||||||
mod := s.ModuleByPath(modPath)
|
mod := s.ModuleByPath(modPath)
|
||||||
if mod == nil {
|
if mod == nil {
|
||||||
|
if allowMissing {
|
||||||
|
return c.allowMissingExit(name, module)
|
||||||
|
}
|
||||||
|
|
||||||
c.Ui.Error(fmt.Sprintf(
|
c.Ui.Error(fmt.Sprintf(
|
||||||
"The module %s could not be found. There is nothing to taint.",
|
"The module %s could not be found. There is nothing to taint.",
|
||||||
module))
|
module))
|
||||||
@ -70,6 +81,10 @@ func (c *TaintCommand) Run(args []string) int {
|
|||||||
|
|
||||||
// If there are no resources in this module, it is an error
|
// If there are no resources in this module, it is an error
|
||||||
if len(mod.Resources) == 0 {
|
if len(mod.Resources) == 0 {
|
||||||
|
if allowMissing {
|
||||||
|
return c.allowMissingExit(name, module)
|
||||||
|
}
|
||||||
|
|
||||||
c.Ui.Error(fmt.Sprintf(
|
c.Ui.Error(fmt.Sprintf(
|
||||||
"The module %s has no resources. There is nothing to taint.",
|
"The module %s has no resources. There is nothing to taint.",
|
||||||
module))
|
module))
|
||||||
@ -79,6 +94,10 @@ func (c *TaintCommand) Run(args []string) int {
|
|||||||
// Get the resource we're looking for
|
// Get the resource we're looking for
|
||||||
rs, ok := mod.Resources[name]
|
rs, ok := mod.Resources[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
if allowMissing {
|
||||||
|
return c.allowMissingExit(name, module)
|
||||||
|
}
|
||||||
|
|
||||||
c.Ui.Error(fmt.Sprintf(
|
c.Ui.Error(fmt.Sprintf(
|
||||||
"The resource %s couldn't be found in the module %s.",
|
"The resource %s couldn't be found in the module %s.",
|
||||||
name,
|
name,
|
||||||
@ -116,6 +135,9 @@ Usage: terraform taint [options] name
|
|||||||
|
|
||||||
Options:
|
Options:
|
||||||
|
|
||||||
|
-allow-missing If specified, the command will succeed (exit code 0)
|
||||||
|
even if the resource is missing.
|
||||||
|
|
||||||
-backup=path Path to backup the existing state file before
|
-backup=path Path to backup the existing state file before
|
||||||
modifying. Defaults to the "-state-out" path with
|
modifying. Defaults to the "-state-out" path with
|
||||||
".backup" extension. Set to "-" to disable backup.
|
".backup" extension. Set to "-" to disable backup.
|
||||||
@ -139,3 +161,11 @@ Options:
|
|||||||
func (c *TaintCommand) Synopsis() string {
|
func (c *TaintCommand) Synopsis() string {
|
||||||
return "Manually mark a resource for recreation"
|
return "Manually mark a resource for recreation"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *TaintCommand) allowMissingExit(name, module string) int {
|
||||||
|
c.Ui.Output(fmt.Sprintf(
|
||||||
|
"The resource %s in the module %s was not found, but\n"+
|
||||||
|
"-allow-missing is set, so we're exiting successfully.",
|
||||||
|
name, module))
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
@ -187,6 +187,75 @@ func TestTaint_defaultState(t *testing.T) {
|
|||||||
testStateOutput(t, path, testTaintStr)
|
testStateOutput(t, path, testTaintStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTaint_missing(t *testing.T) {
|
||||||
|
state := &terraform.State{
|
||||||
|
Modules: []*terraform.ModuleState{
|
||||||
|
&terraform.ModuleState{
|
||||||
|
Path: []string{"root"},
|
||||||
|
Resources: map[string]*terraform.ResourceState{
|
||||||
|
"test_instance.foo": &terraform.ResourceState{
|
||||||
|
Type: "test_instance",
|
||||||
|
Primary: &terraform.InstanceState{
|
||||||
|
ID: "bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
statePath := testStateFile(t, state)
|
||||||
|
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
c := &TaintCommand{
|
||||||
|
Meta: Meta{
|
||||||
|
Ui: ui,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{
|
||||||
|
"-state", statePath,
|
||||||
|
"test_instance.bar",
|
||||||
|
}
|
||||||
|
if code := c.Run(args); code == 0 {
|
||||||
|
t.Fatalf("bad: %d\n\n%s", code, ui.OutputWriter.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTaint_missingAllow(t *testing.T) {
|
||||||
|
state := &terraform.State{
|
||||||
|
Modules: []*terraform.ModuleState{
|
||||||
|
&terraform.ModuleState{
|
||||||
|
Path: []string{"root"},
|
||||||
|
Resources: map[string]*terraform.ResourceState{
|
||||||
|
"test_instance.foo": &terraform.ResourceState{
|
||||||
|
Type: "test_instance",
|
||||||
|
Primary: &terraform.InstanceState{
|
||||||
|
ID: "bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
statePath := testStateFile(t, state)
|
||||||
|
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
c := &TaintCommand{
|
||||||
|
Meta: Meta{
|
||||||
|
Ui: ui,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{
|
||||||
|
"-allow-missing",
|
||||||
|
"-state", statePath,
|
||||||
|
"test_instance.bar",
|
||||||
|
}
|
||||||
|
if code := c.Run(args); code != 0 {
|
||||||
|
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestTaint_stateOut(t *testing.T) {
|
func TestTaint_stateOut(t *testing.T) {
|
||||||
// Get a temp cwd
|
// Get a temp cwd
|
||||||
tmp, cwd := testCwd(t)
|
tmp, cwd := testCwd(t)
|
||||||
|
@ -40,6 +40,10 @@ The format of this argument is `TYPE.NAME`, such as `aws_instance.foo`.
|
|||||||
|
|
||||||
The command-line flags are all optional. The list of available flags are:
|
The command-line flags are all optional. The list of available flags are:
|
||||||
|
|
||||||
|
* `-allow-missing` - If specified, the command will succeed (exit code 0)
|
||||||
|
even if the resource is missing. The command can still error, but only
|
||||||
|
in critically erroneous cases.
|
||||||
|
|
||||||
* `-backup=path` - Path to the backup file. Defaults to `-state-out` with
|
* `-backup=path` - Path to the backup file. Defaults to `-state-out` with
|
||||||
the ".backup" extension. Disabled by setting to "-".
|
the ".backup" extension. Disabled by setting to "-".
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user