command/format: concise diff is now the default (#27079)

* command/format: concise diff is no longer an experiment

Since state formatting goes through the "diff" printer, I have
repurposed the concise flag as a verbose flag, used only when printing
state. It's silly but it works!

* remove helper/experiment
With this experiment concluded, we no longer need helper/experiment. The
shadow experiment had not been touched in many years, so I removed all
references, and removed the package entirely. Any new experiments are
expected to be configuration experiments handled by our (other)
experiments package.

* check for the verbose flag consistently, in case we end up using it in plans in the future
This commit is contained in:
Kristin Laemmert
2020-12-02 15:42:41 -05:00
committed by GitHub
parent b2d0e20759
commit 3fa063b8dc
8 changed files with 15 additions and 791 deletions

View File

@@ -7,7 +7,6 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/configs/configschema"
"github.com/hashicorp/terraform/helper/experiment"
"github.com/hashicorp/terraform/plans"
"github.com/mitchellh/colorstring"
"github.com/zclconf/go-cty/cty"
@@ -362,13 +361,6 @@ new line
~ str = "before" -> "after"
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
~ id = "blah" -> (known after apply)
password = (sensitive value)
~ str = "before" -> "after"
}
`,
},
@@ -502,18 +494,6 @@ new line
}
# (2 unchanged attributes hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
~ ami = "ami-BEFORE" -> "ami-AFTER"
bar = "bar"
foo = "foo"
id = "i-02ae66f368e8518a9"
name = "alice"
tags = {
"name" = "bob"
}
}
`,
},
}
@@ -594,19 +574,6 @@ func TestResourceChange_JSON(t *testing.T) {
)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
~ id = "i-02ae66f368e8518a9" -> (known after apply)
~ json_field = jsonencode(
~ {
aaa = "value"
+ bbb = "new_value"
- ccc = 5 -> null
}
)
}
`,
},
"in-place update (from empty tuple)": {
Action: plans.Update,
@@ -739,17 +706,6 @@ func TestResourceChange_JSON(t *testing.T) {
} # forces replacement
)
}
`,
VerboseOutput: ` # test_instance.example must be replaced
-/+ resource "test_instance" "example" {
~ id = "i-02ae66f368e8518a9" -> (known after apply)
~ json_field = jsonencode(
~ {
aaa = "value"
+ bbb = "new_value"
} # forces replacement
)
}
`,
},
"in-place update (whitespace change)": {
@@ -871,18 +827,6 @@ func TestResourceChange_JSON(t *testing.T) {
]
)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
~ id = "i-02ae66f368e8518a9" -> (known after apply)
~ json_field = jsonencode(
~ [
"first",
"second",
- "third",
]
)
}
`,
},
"JSON list item addition": {
@@ -916,19 +860,6 @@ func TestResourceChange_JSON(t *testing.T) {
)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
~ id = "i-02ae66f368e8518a9" -> (known after apply)
~ json_field = jsonencode(
~ [
"first",
"second",
+ "third",
]
)
}
`,
},
"JSON list object addition": {
Action: plans.Update,
@@ -1223,15 +1154,6 @@ func TestResourceChange_primitiveList(t *testing.T) {
]
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
+ list_field = [
+ "new-element",
]
}
`,
},
"in-place update - first addition": {
@@ -1266,15 +1188,6 @@ func TestResourceChange_primitiveList(t *testing.T) {
]
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
~ list_field = [
+ "new-element",
]
}
`,
},
"in-place update - insertion": {
@@ -1324,20 +1237,6 @@ func TestResourceChange_primitiveList(t *testing.T) {
]
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
~ list_field = [
"aaaa",
"bbbb",
+ "cccc",
"dddd",
"eeee",
"ffff",
]
}
`,
},
"force-new update - insertion": {
@@ -1381,17 +1280,6 @@ func TestResourceChange_primitiveList(t *testing.T) {
]
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example must be replaced
-/+ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
~ list_field = [ # forces replacement
"aaaa",
+ "bbbb",
"cccc",
]
}
`,
},
"in-place update - deletion": {
@@ -1438,19 +1326,6 @@ func TestResourceChange_primitiveList(t *testing.T) {
]
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
~ list_field = [
- "aaaa",
"bbbb",
- "cccc",
"dddd",
"eeee",
]
}
`,
},
"creation - empty list": {
@@ -1515,17 +1390,6 @@ func TestResourceChange_primitiveList(t *testing.T) {
]
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
~ list_field = [
- "aaaa",
- "bbbb",
- "cccc",
]
}
`,
},
"in-place update - null to empty": {
@@ -1556,13 +1420,6 @@ func TestResourceChange_primitiveList(t *testing.T) {
+ list_field = []
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
+ list_field = []
}
`,
},
"update to unknown element": {
@@ -1606,18 +1463,6 @@ func TestResourceChange_primitiveList(t *testing.T) {
]
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
~ list_field = [
"aaaa",
- "bbbb",
+ (known after apply),
"cccc",
]
}
`,
},
"update - two new unknown elements": {
@@ -1668,21 +1513,6 @@ func TestResourceChange_primitiveList(t *testing.T) {
]
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
~ list_field = [
"aaaa",
- "bbbb",
+ (known after apply),
+ (known after apply),
"cccc",
"dddd",
"eeee",
]
}
`,
},
}
@@ -1734,19 +1564,6 @@ func TestResourceChange_primitiveTuple(t *testing.T) {
# (1 unchanged element hidden)
]
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
id = "i-02ae66f368e8518a9"
~ tuple_field = [
"aaaa",
"bbbb",
- "dddd",
+ "cccc",
"eeee",
"ffff",
]
}
`,
},
}
@@ -1787,15 +1604,6 @@ func TestResourceChange_primitiveSet(t *testing.T) {
]
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
+ set_field = [
+ "new-element",
]
}
`,
},
"in-place update - first insertion": {
@@ -1830,15 +1638,6 @@ func TestResourceChange_primitiveSet(t *testing.T) {
]
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
~ set_field = [
+ "new-element",
]
}
`,
},
"in-place update - insertion": {
@@ -1879,17 +1678,6 @@ func TestResourceChange_primitiveSet(t *testing.T) {
]
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
~ set_field = [
"aaaa",
+ "bbbb",
"cccc",
]
}
`,
},
"force-new update - insertion": {
@@ -1932,17 +1720,6 @@ func TestResourceChange_primitiveSet(t *testing.T) {
]
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example must be replaced
-/+ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
~ set_field = [ # forces replacement
"aaaa",
+ "bbbb",
"cccc",
]
}
`,
},
"in-place update - deletion": {
@@ -1983,17 +1760,6 @@ func TestResourceChange_primitiveSet(t *testing.T) {
]
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
~ set_field = [
- "aaaa",
"bbbb",
- "cccc",
]
}
`,
},
"creation - empty set": {
@@ -2055,16 +1821,6 @@ func TestResourceChange_primitiveSet(t *testing.T) {
]
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
~ set_field = [
- "aaaa",
- "bbbb",
]
}
`,
},
"in-place update - null to empty set": {
@@ -2095,13 +1851,6 @@ func TestResourceChange_primitiveSet(t *testing.T) {
+ set_field = []
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
+ set_field = []
}
`,
},
"in-place update to unknown": {
@@ -2138,16 +1887,6 @@ func TestResourceChange_primitiveSet(t *testing.T) {
] -> (known after apply)
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
~ set_field = [
- "aaaa",
- "bbbb",
] -> (known after apply)
}
`,
},
"in-place update to unknown element": {
@@ -2188,17 +1927,6 @@ func TestResourceChange_primitiveSet(t *testing.T) {
]
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
~ set_field = [
"aaaa",
- "bbbb",
~ (known after apply),
]
}
`,
},
}
@@ -2239,15 +1967,6 @@ func TestResourceChange_map(t *testing.T) {
}
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
+ map_field = {
+ "new-key" = "new-element"
}
}
`,
},
"in-place update - first insertion": {
@@ -2282,15 +2001,6 @@ func TestResourceChange_map(t *testing.T) {
}
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
~ map_field = {
+ "new-key" = "new-element"
}
}
`,
},
"in-place update - insertion": {
@@ -2331,17 +2041,6 @@ func TestResourceChange_map(t *testing.T) {
}
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
~ map_field = {
"a" = "aaaa"
+ "b" = "bbbb"
"c" = "cccc"
}
}
`,
},
"force-new update - insertion": {
@@ -2384,17 +2083,6 @@ func TestResourceChange_map(t *testing.T) {
}
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example must be replaced
-/+ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
~ map_field = { # forces replacement
"a" = "aaaa"
+ "b" = "bbbb"
"c" = "cccc"
}
}
`,
},
"in-place update - deletion": {
@@ -2435,17 +2123,6 @@ func TestResourceChange_map(t *testing.T) {
}
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
~ map_field = {
- "a" = "aaaa" -> null
"b" = "bbbb"
- "c" = "cccc" -> null
}
}
`,
},
"creation - empty": {
@@ -2513,17 +2190,6 @@ func TestResourceChange_map(t *testing.T) {
}
# (1 unchanged attribute hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
ami = "ami-STATIC"
~ id = "i-02ae66f368e8518a9" -> (known after apply)
~ map_field = {
"a" = "aaaa"
~ "b" = "bbbb" -> (known after apply)
"c" = "cccc"
}
}
`,
},
}
@@ -2582,16 +2248,6 @@ func TestResourceChange_nestedList(t *testing.T) {
# (1 unchanged block hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
~ ami = "ami-BEFORE" -> "ami-AFTER"
id = "i-02ae66f368e8518a9"
root_block_device {
volume_type = "gp2"
}
}
`,
},
"in-place update - creation": {
@@ -2756,17 +2412,6 @@ func TestResourceChange_nestedList(t *testing.T) {
# (1 unchanged attribute hidden)
}
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
~ ami = "ami-BEFORE" -> "ami-AFTER"
id = "i-02ae66f368e8518a9"
~ root_block_device {
+ new_field = "new_value"
volume_type = "gp2"
}
}
`,
},
"force-new update (inside block)": {
@@ -3344,17 +2989,6 @@ func TestResourceChange_nestedMap(t *testing.T) {
# (1 unchanged attribute hidden)
}
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
~ ami = "ami-BEFORE" -> "ami-AFTER"
id = "i-02ae66f368e8518a9"
~ root_block_device "a" {
+ new_field = "new_value"
volume_type = "gp2"
}
}
`,
},
"in-place update - insertion": {
@@ -3422,20 +3056,6 @@ func TestResourceChange_nestedMap(t *testing.T) {
}
# (1 unchanged block hidden)
}
`,
VerboseOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
~ ami = "ami-BEFORE" -> "ami-AFTER"
id = "i-02ae66f368e8518a9"
root_block_device "a" {
volume_type = "gp2"
}
+ root_block_device "b" {
+ new_field = "new_value"
+ volume_type = "gp2"
}
}
`,
},
"force-new update (whole block)": {
@@ -3500,19 +3120,6 @@ func TestResourceChange_nestedMap(t *testing.T) {
}
# (1 unchanged block hidden)
}
`,
VerboseOutput: ` # test_instance.example must be replaced
-/+ resource "test_instance" "example" {
~ ami = "ami-BEFORE" -> "ami-AFTER"
id = "i-02ae66f368e8518a9"
~ root_block_device "a" { # forces replacement
~ volume_type = "gp2" -> "different"
}
root_block_device "b" {
volume_type = "standard"
}
}
`,
},
"in-place update - deletion": {
@@ -4512,10 +4119,6 @@ type testCase struct {
RequiredReplace cty.PathSet
Tainted bool
ExpectedOutput string
// This field and all associated values can be removed if the concise diff
// experiment succeeds.
VerboseOutput string
}
func runTestCases(t *testing.T, testCases map[string]testCase) {
@@ -4569,25 +4172,11 @@ func runTestCases(t *testing.T, testCases map[string]testCase) {
RequiredReplace: tc.RequiredReplace,
}
experiment.SetEnabled(experiment.X_concise_diff, true)
output := ResourceChange(change, tc.Tainted, tc.Schema, color)
if output != tc.ExpectedOutput {
t.Errorf("Unexpected diff.\ngot:\n%s\nwant:\n%s\n", output, tc.ExpectedOutput)
t.Errorf("%s", cmp.Diff(output, tc.ExpectedOutput))
}
// Temporary coverage for verbose diff behaviour. All lines below
// in this function can be removed if the concise diff experiment
// succeeds.
if tc.VerboseOutput == "" {
return
}
experiment.SetEnabled(experiment.X_concise_diff, false)
output = ResourceChange(change, tc.Tainted, tc.Schema, color)
if output != tc.VerboseOutput {
t.Errorf("Unexpected diff.\ngot:\n%s\nwant:\n%s\n", output, tc.VerboseOutput)
t.Errorf("%s", cmp.Diff(output, tc.VerboseOutput))
}
})
}
}
@@ -4694,7 +4283,6 @@ func TestOutputChanges(t *testing.T) {
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
experiment.SetEnabled(experiment.X_concise_diff, true)
output := OutputChanges(tc.changes, color)
if output != tc.output {
t.Errorf("Unexpected diff.\ngot:\n%s\nwant:\n%s\n", output, tc.output)