mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
plans: indicate when resource deleted due to move (#31695)
Add a new ChangeReason, ReasonDeleteBecauseNoMoveTarget, to provide better information in cases where a planned deletion is due to moving a resource to a target not in configuration. Consider a case in which a resource instance exists in state at address A, and the user adds a moved block to move A to address B. Whether by the user's intention or not, address B does not exist in configuration. Terraform combines the move from A to B, and the lack of configuration for B, into a single delete action for the (previously nonexistent) entity B. Prior to this commit, the Terraform plan will report that resource B will be destroyed because it does not exist in configuration, without explicitly connecting this to the move. This commit provides the user an additional clue as to what has happened, in a case in which Terraform has elided a user's action and inaction into one potentially destructive change.
This commit is contained in:
parent
1347aa29fd
commit
dec48a8510
@ -115,6 +115,8 @@ func ResourceChange(
|
||||
switch change.ActionReason {
|
||||
case plans.ResourceInstanceDeleteBecauseNoResourceConfig:
|
||||
buf.WriteString(fmt.Sprintf("\n # (because %s is not in configuration)", addr.Resource.Resource))
|
||||
case plans.ResourceInstanceDeleteBecauseNoMoveTarget:
|
||||
buf.WriteString(fmt.Sprintf("\n # (because %s was moved to %s, which is not in configuration)", change.PrevRunAddr, addr.Resource.Resource))
|
||||
case plans.ResourceInstanceDeleteBecauseNoModule:
|
||||
// FIXME: Ideally we'd truncate addr.Module to reflect the earliest
|
||||
// step that doesn't exist, so it's clearer which call this refers
|
||||
|
@ -413,6 +413,8 @@ func (p *plan) marshalResourceChanges(resources []*plans.ResourceInstanceChangeS
|
||||
r.ActionReason = "delete_because_each_key"
|
||||
case plans.ResourceInstanceDeleteBecauseNoModule:
|
||||
r.ActionReason = "delete_because_no_module"
|
||||
case plans.ResourceInstanceDeleteBecauseNoMoveTarget:
|
||||
r.ActionReason = "delete_because_no_move_target"
|
||||
case plans.ResourceInstanceReadBecauseConfigUnknown:
|
||||
r.ActionReason = "read_because_config_unknown"
|
||||
case plans.ResourceInstanceReadBecauseDependencyPending:
|
||||
|
@ -80,6 +80,7 @@ const (
|
||||
ReasonDeleteBecauseCountIndex ChangeReason = "delete_because_count_index"
|
||||
ReasonDeleteBecauseEachKey ChangeReason = "delete_because_each_key"
|
||||
ReasonDeleteBecauseNoModule ChangeReason = "delete_because_no_module"
|
||||
ReasonDeleteBecauseNoMoveTarget ChangeReason = "delete_because_no_move_target"
|
||||
ReasonReadBecauseConfigUnknown ChangeReason = "read_because_config_unknown"
|
||||
ReasonReadBecauseDependencyPending ChangeReason = "read_because_dependency_pending"
|
||||
)
|
||||
@ -108,6 +109,8 @@ func changeReason(reason plans.ResourceInstanceChangeActionReason) ChangeReason
|
||||
return ReasonDeleteBecauseNoModule
|
||||
case plans.ResourceInstanceReadBecauseConfigUnknown:
|
||||
return ReasonReadBecauseConfigUnknown
|
||||
case plans.ResourceInstanceDeleteBecauseNoMoveTarget:
|
||||
return ReasonDeleteBecauseNoMoveTarget
|
||||
case plans.ResourceInstanceReadBecauseDependencyPending:
|
||||
return ReasonReadBecauseDependencyPending
|
||||
default:
|
||||
|
@ -427,6 +427,12 @@ const (
|
||||
// specific reasons for a particular instance to no longer be declared.
|
||||
ResourceInstanceDeleteBecauseNoModule ResourceInstanceChangeActionReason = 'M'
|
||||
|
||||
// ResourceInstanceDeleteBecauseNoMoveTarget indicates that the resource
|
||||
// address appears as the target ("to") in a moved block, but no
|
||||
// configuration exists for that resource. According to our move rules,
|
||||
// this combination evaluates to a deletion of the "new" resource.
|
||||
ResourceInstanceDeleteBecauseNoMoveTarget ResourceInstanceChangeActionReason = 'A'
|
||||
|
||||
// ResourceInstanceReadBecauseConfigUnknown indicates that the resource
|
||||
// must be read during apply (rather than during planning) because its
|
||||
// configuration contains unknown values. This reason applies only to
|
||||
|
@ -152,6 +152,7 @@ const (
|
||||
ResourceInstanceActionReason_REPLACE_BY_TRIGGERS ResourceInstanceActionReason = 9
|
||||
ResourceInstanceActionReason_READ_BECAUSE_CONFIG_UNKNOWN ResourceInstanceActionReason = 10
|
||||
ResourceInstanceActionReason_READ_BECAUSE_DEPENDENCY_PENDING ResourceInstanceActionReason = 11
|
||||
ResourceInstanceActionReason_DELETE_BECAUSE_NO_MOVE_TARGET ResourceInstanceActionReason = 12
|
||||
)
|
||||
|
||||
// Enum value maps for ResourceInstanceActionReason.
|
||||
@ -169,6 +170,7 @@ var (
|
||||
9: "REPLACE_BY_TRIGGERS",
|
||||
10: "READ_BECAUSE_CONFIG_UNKNOWN",
|
||||
11: "READ_BECAUSE_DEPENDENCY_PENDING",
|
||||
12: "DELETE_BECAUSE_NO_MOVE_TARGET",
|
||||
}
|
||||
ResourceInstanceActionReason_value = map[string]int32{
|
||||
"NONE": 0,
|
||||
@ -183,6 +185,7 @@ var (
|
||||
"REPLACE_BY_TRIGGERS": 9,
|
||||
"READ_BECAUSE_CONFIG_UNKNOWN": 10,
|
||||
"READ_BECAUSE_DEPENDENCY_PENDING": 11,
|
||||
"DELETE_BECAUSE_NO_MOVE_TARGET": 12,
|
||||
}
|
||||
)
|
||||
|
||||
@ -1391,7 +1394,7 @@ var file_planfile_proto_rawDesc = []byte{
|
||||
0x0a, 0x0a, 0x06, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x05, 0x12, 0x16, 0x0a, 0x12, 0x44,
|
||||
0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x54, 0x48, 0x45, 0x4e, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54,
|
||||
0x45, 0x10, 0x06, 0x12, 0x16, 0x0a, 0x12, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x5f, 0x54, 0x48,
|
||||
0x45, 0x4e, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x07, 0x2a, 0x86, 0x03, 0x0a, 0x1c,
|
||||
0x45, 0x4e, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x07, 0x2a, 0xa9, 0x03, 0x0a, 0x1c,
|
||||
0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65,
|
||||
0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x08, 0x0a, 0x04,
|
||||
0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x45, 0x50, 0x4c, 0x41, 0x43,
|
||||
@ -1416,11 +1419,14 @@ var file_planfile_proto_rawDesc = []byte{
|
||||
0x4f, 0x4e, 0x46, 0x49, 0x47, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x0a, 0x12,
|
||||
0x23, 0x0a, 0x1f, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f,
|
||||
0x44, 0x45, 0x50, 0x45, 0x4e, 0x44, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49,
|
||||
0x4e, 0x47, 0x10, 0x0b, 0x42, 0x42, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
|
||||
0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x74, 0x65, 0x72,
|
||||
0x72, 0x61, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f,
|
||||
0x70, 0x6c, 0x61, 0x6e, 0x73, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70,
|
||||
0x6c, 0x61, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x4e, 0x47, 0x10, 0x0b, 0x12, 0x21, 0x0a, 0x1d, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x42,
|
||||
0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x4e, 0x4f, 0x5f, 0x4d, 0x4f, 0x56, 0x45, 0x5f, 0x54,
|
||||
0x41, 0x52, 0x47, 0x45, 0x54, 0x10, 0x0c, 0x42, 0x42, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75,
|
||||
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f,
|
||||
0x74, 0x65, 0x72, 0x72, 0x61, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
|
||||
0x61, 0x6c, 0x2f, 0x70, 0x6c, 0x61, 0x6e, 0x73, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61,
|
||||
0x6c, 0x2f, 0x70, 0x6c, 0x61, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -151,6 +151,7 @@ enum ResourceInstanceActionReason {
|
||||
REPLACE_BY_TRIGGERS = 9;
|
||||
READ_BECAUSE_CONFIG_UNKNOWN = 10;
|
||||
READ_BECAUSE_DEPENDENCY_PENDING = 11;
|
||||
DELETE_BECAUSE_NO_MOVE_TARGET = 12;
|
||||
}
|
||||
|
||||
message ResourceInstanceChange {
|
||||
|
@ -331,6 +331,8 @@ func resourceChangeFromTfplan(rawChange *planproto.ResourceInstanceChange) (*pla
|
||||
ret.ActionReason = plans.ResourceInstanceReadBecauseConfigUnknown
|
||||
case planproto.ResourceInstanceActionReason_READ_BECAUSE_DEPENDENCY_PENDING:
|
||||
ret.ActionReason = plans.ResourceInstanceReadBecauseDependencyPending
|
||||
case planproto.ResourceInstanceActionReason_DELETE_BECAUSE_NO_MOVE_TARGET:
|
||||
ret.ActionReason = plans.ResourceInstanceDeleteBecauseNoMoveTarget
|
||||
default:
|
||||
return nil, fmt.Errorf("resource has invalid action reason %s", rawChange.ActionReason)
|
||||
}
|
||||
@ -705,6 +707,8 @@ func resourceChangeToTfplan(change *plans.ResourceInstanceChangeSrc) (*planproto
|
||||
ret.ActionReason = planproto.ResourceInstanceActionReason_READ_BECAUSE_CONFIG_UNKNOWN
|
||||
case plans.ResourceInstanceReadBecauseDependencyPending:
|
||||
ret.ActionReason = planproto.ResourceInstanceActionReason_READ_BECAUSE_DEPENDENCY_PENDING
|
||||
case plans.ResourceInstanceDeleteBecauseNoMoveTarget:
|
||||
ret.ActionReason = planproto.ResourceInstanceActionReason_DELETE_BECAUSE_NO_MOVE_TARGET
|
||||
default:
|
||||
return nil, fmt.Errorf("resource %s has unsupported action reason %s", change.Addr, change.ActionReason)
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ func _() {
|
||||
_ = x[ResourceInstanceDeleteBecauseCountIndex-67]
|
||||
_ = x[ResourceInstanceDeleteBecauseEachKey-69]
|
||||
_ = x[ResourceInstanceDeleteBecauseNoModule-77]
|
||||
_ = x[ResourceInstanceDeleteBecauseNoMoveTarget-65]
|
||||
_ = x[ResourceInstanceReadBecauseConfigUnknown-63]
|
||||
_ = x[ResourceInstanceReadBecauseDependencyPending-33]
|
||||
}
|
||||
@ -26,16 +27,17 @@ const (
|
||||
_ResourceInstanceChangeActionReason_name_0 = "ResourceInstanceChangeNoReason"
|
||||
_ResourceInstanceChangeActionReason_name_1 = "ResourceInstanceReadBecauseDependencyPending"
|
||||
_ResourceInstanceChangeActionReason_name_2 = "ResourceInstanceReadBecauseConfigUnknown"
|
||||
_ResourceInstanceChangeActionReason_name_3 = "ResourceInstanceDeleteBecauseCountIndexResourceInstanceReplaceByTriggersResourceInstanceDeleteBecauseEachKeyResourceInstanceReplaceBecauseCannotUpdate"
|
||||
_ResourceInstanceChangeActionReason_name_4 = "ResourceInstanceDeleteBecauseNoModuleResourceInstanceDeleteBecauseNoResourceConfig"
|
||||
_ResourceInstanceChangeActionReason_name_5 = "ResourceInstanceReplaceByRequest"
|
||||
_ResourceInstanceChangeActionReason_name_6 = "ResourceInstanceReplaceBecauseTainted"
|
||||
_ResourceInstanceChangeActionReason_name_7 = "ResourceInstanceDeleteBecauseWrongRepetition"
|
||||
_ResourceInstanceChangeActionReason_name_3 = "ResourceInstanceDeleteBecauseNoMoveTarget"
|
||||
_ResourceInstanceChangeActionReason_name_4 = "ResourceInstanceDeleteBecauseCountIndexResourceInstanceReplaceByTriggersResourceInstanceDeleteBecauseEachKeyResourceInstanceReplaceBecauseCannotUpdate"
|
||||
_ResourceInstanceChangeActionReason_name_5 = "ResourceInstanceDeleteBecauseNoModuleResourceInstanceDeleteBecauseNoResourceConfig"
|
||||
_ResourceInstanceChangeActionReason_name_6 = "ResourceInstanceReplaceByRequest"
|
||||
_ResourceInstanceChangeActionReason_name_7 = "ResourceInstanceReplaceBecauseTainted"
|
||||
_ResourceInstanceChangeActionReason_name_8 = "ResourceInstanceDeleteBecauseWrongRepetition"
|
||||
)
|
||||
|
||||
var (
|
||||
_ResourceInstanceChangeActionReason_index_3 = [...]uint8{0, 39, 72, 108, 150}
|
||||
_ResourceInstanceChangeActionReason_index_4 = [...]uint8{0, 37, 82}
|
||||
_ResourceInstanceChangeActionReason_index_4 = [...]uint8{0, 39, 72, 108, 150}
|
||||
_ResourceInstanceChangeActionReason_index_5 = [...]uint8{0, 37, 82}
|
||||
)
|
||||
|
||||
func (i ResourceInstanceChangeActionReason) String() string {
|
||||
@ -46,18 +48,20 @@ func (i ResourceInstanceChangeActionReason) String() string {
|
||||
return _ResourceInstanceChangeActionReason_name_1
|
||||
case i == 63:
|
||||
return _ResourceInstanceChangeActionReason_name_2
|
||||
case i == 65:
|
||||
return _ResourceInstanceChangeActionReason_name_3
|
||||
case 67 <= i && i <= 70:
|
||||
i -= 67
|
||||
return _ResourceInstanceChangeActionReason_name_3[_ResourceInstanceChangeActionReason_index_3[i]:_ResourceInstanceChangeActionReason_index_3[i+1]]
|
||||
return _ResourceInstanceChangeActionReason_name_4[_ResourceInstanceChangeActionReason_index_4[i]:_ResourceInstanceChangeActionReason_index_4[i+1]]
|
||||
case 77 <= i && i <= 78:
|
||||
i -= 77
|
||||
return _ResourceInstanceChangeActionReason_name_4[_ResourceInstanceChangeActionReason_index_4[i]:_ResourceInstanceChangeActionReason_index_4[i+1]]
|
||||
return _ResourceInstanceChangeActionReason_name_5[_ResourceInstanceChangeActionReason_index_5[i]:_ResourceInstanceChangeActionReason_index_5[i+1]]
|
||||
case i == 82:
|
||||
return _ResourceInstanceChangeActionReason_name_5
|
||||
case i == 84:
|
||||
return _ResourceInstanceChangeActionReason_name_6
|
||||
case i == 87:
|
||||
case i == 84:
|
||||
return _ResourceInstanceChangeActionReason_name_7
|
||||
case i == 87:
|
||||
return _ResourceInstanceChangeActionReason_name_8
|
||||
default:
|
||||
return "ResourceInstanceChangeActionReason(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
|
@ -157,6 +157,13 @@ func (n *NodePlannableResourceInstanceOrphan) managedResourceExecute(ctx EvalCon
|
||||
func (n *NodePlannableResourceInstanceOrphan) deleteActionReason(ctx EvalContext) plans.ResourceInstanceChangeActionReason {
|
||||
cfg := n.Config
|
||||
if cfg == nil {
|
||||
if !n.Addr.Equal(n.prevRunAddr(ctx)) {
|
||||
// This means the resource was moved - see also
|
||||
// ResourceInstanceChange.Moved() which calculates
|
||||
// this the same way.
|
||||
return plans.ResourceInstanceDeleteBecauseNoMoveTarget
|
||||
}
|
||||
|
||||
return plans.ResourceInstanceDeleteBecauseNoResourceConfig
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user