From b699391d04faf00641d0c30d24bd55dd679d946c Mon Sep 17 00:00:00 2001 From: Alisdair McDiarmid Date: Fri, 24 Sep 2021 11:18:39 -0400 Subject: [PATCH] json-output: Add change reasons to explain deletes The extra feedback information for why resource instance deletion is planned is now included in the streaming JSON UI output. We also add an explicit case for no-op actions to switch statements in this package to ensure exhaustiveness, for future linting. --- internal/command/views/json/change.go | 16 ++++++++++++++++ internal/command/views/json/hook.go | 12 ++++++++++++ .../docs/internals/machine-readable-ui.html.md | 7 ++++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/internal/command/views/json/change.go b/internal/command/views/json/change.go index c18a2c15a..4a8aa4e5b 100644 --- a/internal/command/views/json/change.go +++ b/internal/command/views/json/change.go @@ -73,6 +73,12 @@ const ( ReasonRequested ChangeReason = "requested" ReasonCannotUpdate ChangeReason = "cannot_update" ReasonUnknown ChangeReason = "unknown" + + ReasonDeleteBecauseNoResourceConfig ChangeReason = "delete_because_no_resource_config" + ReasonDeleteBecauseWrongRepetition ChangeReason = "delete_because_wrong_repetition" + ReasonDeleteBecauseCountIndex ChangeReason = "delete_because_count_index" + ReasonDeleteBecauseEachKey ChangeReason = "delete_because_each_key" + ReasonDeleteBecauseNoModule ChangeReason = "delete_because_no_module" ) func changeReason(reason plans.ResourceInstanceChangeActionReason) ChangeReason { @@ -85,6 +91,16 @@ func changeReason(reason plans.ResourceInstanceChangeActionReason) ChangeReason return ReasonRequested case plans.ResourceInstanceReplaceBecauseCannotUpdate: return ReasonCannotUpdate + case plans.ResourceInstanceDeleteBecauseNoResourceConfig: + return ReasonDeleteBecauseNoResourceConfig + case plans.ResourceInstanceDeleteBecauseWrongRepetition: + return ReasonDeleteBecauseWrongRepetition + case plans.ResourceInstanceDeleteBecauseCountIndex: + return ReasonDeleteBecauseCountIndex + case plans.ResourceInstanceDeleteBecauseEachKey: + return ReasonDeleteBecauseEachKey + case plans.ResourceInstanceDeleteBecauseNoModule: + return ReasonDeleteBecauseNoModule default: // This should never happen, but there's no good way to guarantee // exhaustive handling of the enum, so a generic fall back is better diff --git a/internal/command/views/json/hook.go b/internal/command/views/json/hook.go index 1736e10a5..142a4d1fd 100644 --- a/internal/command/views/json/hook.go +++ b/internal/command/views/json/hook.go @@ -314,6 +314,10 @@ func startActionVerb(action plans.Action) string { // This is not currently possible to reach, as we receive separate // passes for create and delete return "Replacing" + case plans.NoOp: + // This should never be possible: a no-op planned change should not + // be applied. We'll fall back to "Applying". + fallthrough default: return "Applying" } @@ -336,6 +340,10 @@ func progressActionVerb(action plans.Action) string { // This is not currently possible to reach, as we receive separate // passes for create and delete return "replacing" + case plans.NoOp: + // This should never be possible: a no-op planned change should not + // be applied. We'll fall back to "applying". + fallthrough default: return "applying" } @@ -358,6 +366,10 @@ func actionNoun(action plans.Action) string { // This is not currently possible to reach, as we receive separate // passes for create and delete return "Replacement" + case plans.NoOp: + // This should never be possible: a no-op planned change should not + // be applied. We'll fall back to "Apply". + fallthrough default: return "Apply" } diff --git a/website/docs/internals/machine-readable-ui.html.md b/website/docs/internals/machine-readable-ui.html.md index 53b3e47e0..94427cc6d 100644 --- a/website/docs/internals/machine-readable-ui.html.md +++ b/website/docs/internals/machine-readable-ui.html.md @@ -126,10 +126,15 @@ At the end of a plan or before an apply, Terraform will emit a `planned_change` - `resource`: object describing the address of the resource to be changed; see [resource object](#resource-object) below for details - `previous_resource`: object describing the previous address of the resource, if this change includes a configuration-driven move - `action`: the action planned to be taken for the resource. Values: `noop`, `create`, `read`, `update`, `replace`, `delete`, `move`. -- `reason`: an optional reason for the change, currently only used when the action is `replace`. Values: +- `reason`: an optional reason for the change, currently only used when the action is `replace` or `delete`. Values: - `tainted`: resource was marked as tainted - `requested`: user requested that the resource be replaced, for example via the `-replace` plan flag - `cannot_update`: changes to configuration force the resource to be deleted and created rather than updated + - `delete_because_no_resource_config`: no matching resource in configuration + - `delete_because_wrong_repetition`: resource instance key has no corresponding `count` or `for_each` in configuration + - `delete_because_count_index`: resource instance key is outside the range of the `count` argument + - `delete_because_each_key`: resource instance key is not included in the `for_each` argument + - `delete_because_no_module`: enclosing module instance is not in configuration This message does not include details about the exact changes which caused the change to be planned. That information is available in [the JSON plan output](./json-format.html).