add number of action invocations to change summary

equivalence-testing/add-action-invocations-to-summary
Daniel Schmidt 7 months ago
parent eee744c887
commit ecfbdaf18d

@ -1,8 +1,8 @@
{"@level":"info","@message":"Terraform 0.15.0-dev","@module":"terraform.ui","terraform":"0.15.0-dev","type":"version","ui":"0.1.0"}
{"@level":"warn","@message":"Warning: Deprecated flag: -state","@module":"terraform.ui","diagnostic":{"detail":"Use the \"path\" attribute within the \"local\" backend to specify a file for state storage","severity":"warning","summary":"Deprecated flag: -state"},"type":"diagnostic"}
{"@level":"info","@message":"test_instance.foo: Plan to create","@module":"terraform.ui","change":{"resource":{"addr":"test_instance.foo","module":"","resource":"test_instance.foo","implied_provider":"test","resource_type":"test_instance","resource_name":"foo","resource_key":null},"action":"create"},"type":"planned_change"}
{"@level":"info","@message":"Plan: 1 to add, 0 to change, 0 to destroy.","@module":"terraform.ui","changes":{"add":1,"import":0,"change":0,"remove":0,"operation":"plan"},"type":"change_summary"}
{"@level":"info","@message":"Plan: 1 to add, 0 to change, 0 to destroy.","@module":"terraform.ui","changes":{"action_invocation":0,"add":1,"import":0,"change":0,"remove":0,"operation":"plan"},"type":"change_summary"}
{"@level":"info","@message":"test_instance.foo: Creating...","@module":"terraform.ui","hook":{"resource":{"addr":"test_instance.foo","module":"","resource":"test_instance.foo","implied_provider":"test","resource_type":"test_instance","resource_name":"foo","resource_key":null},"action":"create"},"type":"apply_start"}
{"@level":"info","@message":"test_instance.foo: Creation complete after 0s","@module":"terraform.ui","hook":{"resource":{"addr":"test_instance.foo","module":"","resource":"test_instance.foo","implied_provider":"test","resource_type":"test_instance","resource_name":"foo","resource_key":null},"action":"create","elapsed_seconds":0},"type":"apply_complete"}
{"@level":"info","@message":"Apply complete! Resources: 1 added, 0 changed, 0 destroyed.","@module":"terraform.ui","changes":{"add":1,"import":0,"change":0,"remove":0,"operation":"apply"},"type":"change_summary"}
{"@level":"info","@message":"Apply complete! Resources: 1 added, 0 changed, 0 destroyed.","@module":"terraform.ui","changes":{"action_invocation":0,"add":1,"import":0,"change":0,"remove":0,"operation":"apply"},"type":"change_summary"}
{"@level":"info","@message":"Outputs: 0","@module":"terraform.ui","outputs":{},"type":"outputs"}

@ -2,4 +2,4 @@
{"@level":"info","@message":"data.test_data_source.a: Refreshing...","@module":"terraform.ui","hook":{"resource":{"addr":"data.test_data_source.a","module":"","resource":"data.test_data_source.a","implied_provider":"test","resource_type":"test_data_source","resource_name":"a","resource_key":null},"action":"read"},"type":"apply_start"}
{"@level":"info","@message":"data.test_data_source.a: Refresh complete after 0s [id=zzzzz]","@module":"terraform.ui","hook":{"resource":{"addr":"data.test_data_source.a","module":"","resource":"data.test_data_source.a","implied_provider":"test","resource_type":"test_data_source","resource_name":"a","resource_key":null},"action":"read","id_key":"id","id_value":"zzzzz","elapsed_seconds":0},"type":"apply_complete"}
{"@level":"info","@message":"test_instance.foo: Plan to create","@module":"terraform.ui","change":{"resource":{"addr":"test_instance.foo","module":"","resource":"test_instance.foo","implied_provider":"test","resource_type":"test_instance","resource_name":"foo","resource_key":null},"action":"create"},"type":"planned_change"}
{"@level":"info","@message":"Plan: 1 to add, 0 to change, 0 to destroy.","@module":"terraform.ui","changes":{"add":1,"import":0,"change":0,"remove":0,"operation":"plan"},"type":"change_summary"}
{"@level":"info","@message":"Plan: 1 to add, 0 to change, 0 to destroy.","@module":"terraform.ui","changes":{"action_invocation":0,"add":1,"import":0,"change":0,"remove":0,"operation":"plan"},"type":"change_summary"}

@ -138,11 +138,12 @@ func (v *ApplyJSON) ResourceCount(stateOutPath string) {
operation = json.OperationDestroyed
}
v.view.ChangeSummary(&json.ChangeSummary{
Add: v.countHook.Added,
Change: v.countHook.Changed,
Remove: v.countHook.Removed,
Import: v.countHook.Imported,
Operation: operation,
Add: v.countHook.Added,
Change: v.countHook.Changed,
Remove: v.countHook.Removed,
Import: v.countHook.Imported,
ActionInvocation: v.countHook.ActionInvocation,
Operation: operation,
})
}

@ -16,10 +16,11 @@ import (
// countHook is a hook that counts the number of resources
// added, removed, changed during the course of an apply.
type countHook struct {
Added int
Changed int
Removed int
Imported int
Added int
Changed int
Removed int
Imported int
ActionInvocation int
ToAdd int
ToChange int
@ -43,6 +44,7 @@ func (h *countHook) Reset() {
h.Changed = 0
h.Removed = 0
h.Imported = 0
h.ActionInvocation = 0
}
func (h *countHook) PreApply(id terraform.HookResourceIdentity, dk addrs.DeposedKey, action plans.Action, priorState, plannedNewState cty.Value) (terraform.HookAction, error) {
@ -116,3 +118,11 @@ func (h *countHook) PostApplyImport(id terraform.HookResourceIdentity, importing
h.Imported++
return terraform.HookActionContinue, nil
}
func (h *countHook) CompleteAction(id terraform.HookActionIdentity, err error) (terraform.HookAction, error) {
h.Lock()
defer h.Unlock()
h.ActionInvocation++
return terraform.HookActionContinue, nil
}

@ -3,7 +3,10 @@
package json
import "fmt"
import (
"fmt"
"strings"
)
type Operation string
@ -14,31 +17,46 @@ const (
)
type ChangeSummary struct {
Add int `json:"add"`
Change int `json:"change"`
Import int `json:"import"`
Remove int `json:"remove"`
Operation Operation `json:"operation"`
Add int `json:"add"`
Change int `json:"change"`
Import int `json:"import"`
Remove int `json:"remove"`
ActionInvocation int `json:"action_invocation"`
Operation Operation `json:"operation"`
}
// The summary strings for apply and plan are accidentally a public interface
// used by HCP Terraform and Terraform Enterprise, so the exact formats of
// these strings are important.
func (cs *ChangeSummary) String() string {
var buf strings.Builder
switch cs.Operation {
case OperationApplied:
buf.WriteString("Apply complete! Resources: ")
if cs.Import > 0 {
return fmt.Sprintf("Apply complete! Resources: %d imported, %d added, %d changed, %d destroyed.", cs.Import, cs.Add, cs.Change, cs.Remove)
buf.WriteString(fmt.Sprintf("%d imported, ", cs.Import))
}
buf.WriteString(fmt.Sprintf("%d added, %d changed, %d destroyed.", cs.Add, cs.Change, cs.Remove))
if cs.ActionInvocation > 0 {
buf.WriteString(fmt.Sprintf(" %d actions invoked.", cs.ActionInvocation))
}
return fmt.Sprintf("Apply complete! Resources: %d added, %d changed, %d destroyed.", cs.Add, cs.Change, cs.Remove)
case OperationDestroyed:
return fmt.Sprintf("Destroy complete! Resources: %d destroyed.", cs.Remove)
buf.WriteString(fmt.Sprintf("Destroy complete! Resources: %d destroyed.", cs.Remove))
if cs.ActionInvocation > 0 {
buf.WriteString(fmt.Sprintf(" %d actions invoked.", cs.ActionInvocation))
}
case OperationPlanned:
buf.WriteString("Plan: ")
if cs.Import > 0 {
return fmt.Sprintf("Plan: %d to import, %d to add, %d to change, %d to destroy.", cs.Import, cs.Add, cs.Change, cs.Remove)
buf.WriteString(fmt.Sprintf("%d to import, ", cs.Import))
}
buf.WriteString(fmt.Sprintf("%d to add, %d to change, %d to destroy.", cs.Add, cs.Change, cs.Remove))
if cs.ActionInvocation > 0 {
buf.WriteString(fmt.Sprintf(" %d actions to be invoked.", cs.ActionInvocation))
}
return fmt.Sprintf("Plan: %d to add, %d to change, %d to destroy.", cs.Add, cs.Change, cs.Remove)
default:
return fmt.Sprintf("%s: %d add, %d change, %d destroy", cs.Operation, cs.Add, cs.Change, cs.Remove)
buf.WriteString(fmt.Sprintf("%s: %d add, %d change, %d destroy", cs.Operation, cs.Add, cs.Change, cs.Remove))
}
return buf.String()
}

@ -252,11 +252,12 @@ func TestJSONView_ChangeSummary(t *testing.T) {
"@module": "terraform.ui",
"type": "change_summary",
"changes": map[string]interface{}{
"add": float64(1),
"import": float64(0),
"change": float64(2),
"remove": float64(3),
"operation": "apply",
"action_invocation": float64(0),
"add": float64(1),
"import": float64(0),
"change": float64(2),
"remove": float64(3),
"operation": "apply",
},
},
}
@ -282,11 +283,75 @@ func TestJSONView_ChangeSummaryWithImport(t *testing.T) {
"@module": "terraform.ui",
"type": "change_summary",
"changes": map[string]interface{}{
"add": float64(1),
"change": float64(2),
"remove": float64(3),
"import": float64(1),
"operation": "apply",
"action_invocation": float64(0),
"add": float64(1),
"change": float64(2),
"remove": float64(3),
"import": float64(1),
"operation": "apply",
},
},
}
testJSONViewOutputEquals(t, done(t).Stdout(), want)
}
func TestJSONView_ChangeSummaryWithActionInvocations(t *testing.T) {
streams, done := terminal.StreamsForTesting(t)
jv := NewJSONView(NewView(streams))
jv.ChangeSummary(&viewsjson.ChangeSummary{
Add: 1,
Change: 2,
Remove: 3,
ActionInvocation: 23,
Operation: viewsjson.OperationApplied,
})
want := []map[string]interface{}{
{
"@level": "info",
"@message": "Apply complete! Resources: 1 added, 2 changed, 3 destroyed. 23 actions invoked.",
"@module": "terraform.ui",
"type": "change_summary",
"changes": map[string]interface{}{
"action_invocation": float64(23),
"add": float64(1),
"change": float64(2),
"remove": float64(3),
"import": float64(0),
"operation": "apply",
},
},
}
testJSONViewOutputEquals(t, done(t).Stdout(), want)
}
func TestJSONView_ChangeSummaryWithActionInvocationsAndImports(t *testing.T) {
streams, done := terminal.StreamsForTesting(t)
jv := NewJSONView(NewView(streams))
jv.ChangeSummary(&viewsjson.ChangeSummary{
Add: 1,
Change: 2,
Remove: 3,
Import: 2,
ActionInvocation: 23,
Operation: viewsjson.OperationApplied,
})
want := []map[string]interface{}{
{
"@level": "info",
"@message": "Apply complete! Resources: 2 imported, 1 added, 2 changed, 3 destroyed. 23 actions invoked.",
"@module": "terraform.ui",
"type": "change_summary",
"changes": map[string]interface{}{
"action_invocation": float64(23),
"add": float64(1),
"change": float64(2),
"remove": float64(3),
"import": float64(2),
"operation": "apply",
},
},
}

@ -254,6 +254,7 @@ func (v *OperationJSON) Plan(plan *plans.Plan, schemas *terraform.Schemas) {
v.view.PlannedChange(json.NewResourceInstanceChange(change))
}
}
cs.ActionInvocation = len(plan.Changes.ActionInvocations)
v.view.ChangeSummary(cs)

@ -573,11 +573,12 @@ func TestOperationJSON_planNoChanges(t *testing.T) {
"@module": "terraform.ui",
"type": "change_summary",
"changes": map[string]interface{}{
"operation": "plan",
"add": float64(0),
"import": float64(0),
"change": float64(0),
"remove": float64(0),
"operation": "plan",
"action_invocation": float64(0),
"add": float64(0),
"import": float64(0),
"change": float64(0),
"remove": float64(0),
},
},
}
@ -741,11 +742,12 @@ func TestOperationJSON_plan(t *testing.T) {
"@module": "terraform.ui",
"type": "change_summary",
"changes": map[string]interface{}{
"operation": "plan",
"add": float64(3),
"import": float64(0),
"change": float64(1),
"remove": float64(3),
"operation": "plan",
"action_invocation": float64(0),
"add": float64(3),
"import": float64(0),
"change": float64(1),
"remove": float64(3),
},
},
}
@ -888,11 +890,12 @@ func TestOperationJSON_planWithImport(t *testing.T) {
"@module": "terraform.ui",
"type": "change_summary",
"changes": map[string]interface{}{
"operation": "plan",
"add": float64(1),
"import": float64(4),
"change": float64(1),
"remove": float64(2),
"operation": "plan",
"action_invocation": float64(0),
"add": float64(1),
"import": float64(4),
"change": float64(1),
"remove": float64(2),
},
},
}
@ -1025,11 +1028,12 @@ func TestOperationJSON_planDriftWithMove(t *testing.T) {
"@module": "terraform.ui",
"type": "change_summary",
"changes": map[string]interface{}{
"operation": "plan",
"add": float64(0),
"import": float64(0),
"change": float64(0),
"remove": float64(0),
"operation": "plan",
"action_invocation": float64(0),
"add": float64(0),
"import": float64(0),
"change": float64(0),
"remove": float64(0),
},
},
}
@ -1156,11 +1160,12 @@ func TestOperationJSON_planDriftWithMoveRefreshOnly(t *testing.T) {
"@module": "terraform.ui",
"type": "change_summary",
"changes": map[string]interface{}{
"operation": "plan",
"add": float64(0),
"import": float64(0),
"change": float64(0),
"remove": float64(0),
"operation": "plan",
"action_invocation": float64(0),
"add": float64(0),
"import": float64(0),
"change": float64(0),
"remove": float64(0),
},
},
}
@ -1216,11 +1221,12 @@ func TestOperationJSON_planOutputChanges(t *testing.T) {
"@module": "terraform.ui",
"type": "change_summary",
"changes": map[string]interface{}{
"operation": "plan",
"add": float64(0),
"import": float64(0),
"change": float64(0),
"remove": float64(0),
"operation": "plan",
"action_invocation": float64(0),
"add": float64(0),
"import": float64(0),
"change": float64(0),
"remove": float64(0),
},
},
// Output changes

Loading…
Cancel
Save