command/views: Add reason to JSON planned change
Now that we have extra information about the reason for a given resource action, include that in the JSON log output for planned changes.
This commit is contained in:
parent
6bed3008a5
commit
7b23fa7877
|
@ -10,6 +10,7 @@ func NewResourceInstanceChange(change *plans.ResourceInstanceChangeSrc) *Resourc
|
||||||
c := &ResourceInstanceChange{
|
c := &ResourceInstanceChange{
|
||||||
Resource: newResourceAddr(change.Addr),
|
Resource: newResourceAddr(change.Addr),
|
||||||
Action: changeAction(change.Action),
|
Action: changeAction(change.Action),
|
||||||
|
Reason: changeReason(change.ActionReason),
|
||||||
}
|
}
|
||||||
|
|
||||||
return c
|
return c
|
||||||
|
@ -18,6 +19,7 @@ func NewResourceInstanceChange(change *plans.ResourceInstanceChangeSrc) *Resourc
|
||||||
type ResourceInstanceChange struct {
|
type ResourceInstanceChange struct {
|
||||||
Resource ResourceAddr `json:"resource"`
|
Resource ResourceAddr `json:"resource"`
|
||||||
Action ChangeAction `json:"action"`
|
Action ChangeAction `json:"action"`
|
||||||
|
Reason ChangeReason `json:"reason,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ResourceInstanceChange) String() string {
|
func (c *ResourceInstanceChange) String() string {
|
||||||
|
@ -53,3 +55,31 @@ func changeAction(action plans.Action) ChangeAction {
|
||||||
return ActionNoOp
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -433,9 +433,16 @@ func TestOperationJSON_plannedChange(t *testing.T) {
|
||||||
boop := addrs.Resource{Mode: addrs.ManagedResourceMode, Type: "test_instance", Name: "boop"}
|
boop := addrs.Resource{Mode: addrs.ManagedResourceMode, Type: "test_instance", Name: "boop"}
|
||||||
derp := addrs.Resource{Mode: addrs.DataResourceMode, Type: "test_source", Name: "derp"}
|
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
|
// Simple create
|
||||||
v.PlannedChange(&plans.ResourceInstanceChangeSrc{
|
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},
|
ChangeSrc: plans.ChangeSrc{Action: plans.Create},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -445,15 +452,16 @@ func TestOperationJSON_plannedChange(t *testing.T) {
|
||||||
ChangeSrc: plans.ChangeSrc{Action: plans.Delete},
|
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{}{
|
want := []map[string]interface{}{
|
||||||
{
|
{
|
||||||
"@level": "info",
|
"@level": "info",
|
||||||
"@message": "test_instance.boop[0]: Plan to create",
|
"@message": "test_instance.boop[0]: Plan to replace",
|
||||||
"@module": "terraform.ui",
|
"@module": "terraform.ui",
|
||||||
"type": "planned_change",
|
"type": "planned_change",
|
||||||
"change": map[string]interface{}{
|
"change": map[string]interface{}{
|
||||||
"action": "create",
|
"action": "replace",
|
||||||
|
"reason": "requested",
|
||||||
"resource": map[string]interface{}{
|
"resource": map[string]interface{}{
|
||||||
"addr": `test_instance.boop[0]`,
|
"addr": `test_instance.boop[0]`,
|
||||||
"implied_provider": "test",
|
"implied_provider": "test",
|
||||||
|
@ -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)
|
testJSONViewOutputEquals(t, done(t).Stdout(), want)
|
||||||
|
|
Loading…
Reference in New Issue