json-output: Add output changes to plan logs

Extend the outputs JSON log message to support an `action` field (and
make the `type` and `value` fields optional). This allows us to emit a
useful output change summary as part of the plan, bringing the JSON log
output into parity with the text output.

While we do have access to the before/after values in the output
changes, attempting to wedge those into a structured log message is not
appropriate. That level of detail can be extracted from the JSON plan
output from `terraform show -json`.
This commit is contained in:
Alisdair McDiarmid
2021-07-30 13:37:23 -04:00
parent 2f152f1139
commit 3b33dc1105
5 changed files with 207 additions and 5 deletions

View File

@@ -5,7 +5,9 @@ import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/terraform/internal/addrs"
"github.com/hashicorp/terraform/internal/lang/marks"
"github.com/hashicorp/terraform/internal/plans"
"github.com/hashicorp/terraform/internal/states"
"github.com/zclconf/go-cty/cty"
)
@@ -69,6 +71,95 @@ func TestOutputsFromMap(t *testing.T) {
}
}
func TestOutputsFromChanges(t *testing.T) {
root := addrs.RootModuleInstance
num, err := plans.NewDynamicValue(cty.NumberIntVal(1234), cty.Number)
str, err := plans.NewDynamicValue(cty.StringVal("1234"), cty.String)
if err != nil {
t.Fatalf("unexpected error creating dynamic value: %v", err)
}
got := OutputsFromChanges([]*plans.OutputChangeSrc{
// Unchanged output "boop", value 1234
{
Addr: root.OutputValue("boop"),
ChangeSrc: plans.ChangeSrc{
Action: plans.NoOp,
Before: num,
After: num,
},
Sensitive: false,
},
// New output "beep", value 1234
{
Addr: root.OutputValue("beep"),
ChangeSrc: plans.ChangeSrc{
Action: plans.Create,
Before: nil,
After: num,
},
Sensitive: false,
},
// Deleted output "blorp", prior value 1234
{
Addr: root.OutputValue("blorp"),
ChangeSrc: plans.ChangeSrc{
Action: plans.Delete,
Before: num,
After: nil,
},
Sensitive: false,
},
// Updated output "honk", prior value 1234, new value "1234"
{
Addr: root.OutputValue("honk"),
ChangeSrc: plans.ChangeSrc{
Action: plans.Update,
Before: num,
After: str,
},
Sensitive: false,
},
// New sensitive output "secret", value "1234"
{
Addr: root.OutputValue("secret"),
ChangeSrc: plans.ChangeSrc{
Action: plans.Create,
Before: nil,
After: str,
},
Sensitive: true,
},
})
want := Outputs{
"boop": {
Action: "noop",
Sensitive: false,
},
"beep": {
Action: "create",
Sensitive: false,
},
"blorp": {
Action: "delete",
Sensitive: false,
},
"honk": {
Action: "update",
Sensitive: false,
},
"secret": {
Action: "create",
Sensitive: true,
},
}
if !cmp.Equal(want, got) {
t.Fatalf("unexpected result\n%s", cmp.Diff(want, got))
}
}
func TestOutputs_String(t *testing.T) {
outputs := Outputs{
"boop": {