Skip to content

Commit

Permalink
command/views: Add reason to JSON planned change
Browse files Browse the repository at this point in the history
Now that we have extra information about the reason for a given resource
action, include that in the JSON log output for planned changes.
  • Loading branch information
alisdair committed May 3, 2021
1 parent 6bed300 commit 7b23fa7
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 4 deletions.
30 changes: 30 additions & 0 deletions command/views/json/change.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ func NewResourceInstanceChange(change *plans.ResourceInstanceChangeSrc) *Resourc
c := &ResourceInstanceChange{
Resource: newResourceAddr(change.Addr),
Action: changeAction(change.Action),
Reason: changeReason(change.ActionReason),
}

return c
Expand All @@ -18,6 +19,7 @@ func NewResourceInstanceChange(change *plans.ResourceInstanceChangeSrc) *Resourc
type ResourceInstanceChange struct {
Resource ResourceAddr `json:"resource"`
Action ChangeAction `json:"action"`
Reason ChangeReason `json:"reason,omitempty"`
}

func (c *ResourceInstanceChange) String() string {
Expand Down Expand Up @@ -53,3 +55,31 @@ func changeAction(action plans.Action) ChangeAction {
return ActionNoOp
}
}

type ChangeReason string

const (
ReasonNone ChangeReason = ""
ReasonTainted ChangeReason = "tainted"
ReasonRequested ChangeReason = "requested"
ReasonCannotUpdate ChangeReason = "cannot_update"
ReasonUnknown ChangeReason = "unknown"
)

func changeReason(reason plans.ResourceInstanceChangeActionReason) ChangeReason {
switch reason {
case plans.ResourceInstanceChangeNoReason:
return ReasonNone
case plans.ResourceInstanceReplaceBecauseTainted:
return ReasonTainted
case plans.ResourceInstanceReplaceByRequest:
return ReasonRequested
case plans.ResourceInstanceReplaceBecauseCannotUpdate:
return ReasonCannotUpdate
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
// than a misleading result or a panic
return ReasonUnknown
}
}
34 changes: 30 additions & 4 deletions command/views/operation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,9 +433,16 @@ func TestOperationJSON_plannedChange(t *testing.T) {
boop := addrs.Resource{Mode: addrs.ManagedResourceMode, Type: "test_instance", Name: "boop"}
derp := addrs.Resource{Mode: addrs.DataResourceMode, Type: "test_source", Name: "derp"}

// Replace requested by user
v.PlannedChange(&plans.ResourceInstanceChangeSrc{
Addr: boop.Instance(addrs.IntKey(0)).Absolute(root),
ChangeSrc: plans.ChangeSrc{Action: plans.DeleteThenCreate},
ActionReason: plans.ResourceInstanceReplaceByRequest,
})

// Simple create
v.PlannedChange(&plans.ResourceInstanceChangeSrc{
Addr: boop.Instance(addrs.IntKey(0)).Absolute(root),
Addr: boop.Instance(addrs.IntKey(1)).Absolute(root),
ChangeSrc: plans.ChangeSrc{Action: plans.Create},
})

Expand All @@ -445,15 +452,16 @@ func TestOperationJSON_plannedChange(t *testing.T) {
ChangeSrc: plans.ChangeSrc{Action: plans.Delete},
})

// Expect one message only, as the data source deletion should be a no-op
// Expect only two messages, as the data source deletion should be a no-op
want := []map[string]interface{}{
{
"@level": "info",
"@message": "test_instance.boop[0]: Plan to create",
"@message": "test_instance.boop[0]: Plan to replace",
"@module": "terraform.ui",
"type": "planned_change",
"change": map[string]interface{}{
"action": "create",
"action": "replace",
"reason": "requested",
"resource": map[string]interface{}{
"addr": `test_instance.boop[0]`,
"implied_provider": "test",
Expand All @@ -465,6 +473,24 @@ func TestOperationJSON_plannedChange(t *testing.T) {
},
},
},
{
"@level": "info",
"@message": "test_instance.boop[1]: Plan to create",
"@module": "terraform.ui",
"type": "planned_change",
"change": map[string]interface{}{
"action": "create",
"resource": map[string]interface{}{
"addr": `test_instance.boop[1]`,
"implied_provider": "test",
"module": "",
"resource": `test_instance.boop[1]`,
"resource_key": float64(1),
"resource_name": "boop",
"resource_type": "test_instance",
},
},
},
}

testJSONViewOutputEquals(t, done(t).Stdout(), want)
Expand Down

0 comments on commit 7b23fa7

Please sign in to comment.