Skip to content

Commit 3326ab7

Browse files
committed
json-output: Omit unchanged resource_drift entries
Previously, if any resources were found to have drifted, the JSON plan output would include a drift entry for every resource in state. This commit aligns the JSON plan output with the CLI UI, and only includes those resources where the old value does not equal the new value---i.e. drift has been detected. Also fixes a bug where the "address" field was missing from the drift output, and adds some test coverage.
1 parent af68a1e commit 3326ab7

File tree

6 files changed

+268
-0
lines changed

6 files changed

+268
-0
lines changed

internal/command/jsonplan/plan.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,12 @@ func (p *plan) marshalResourceDrift(oldState, newState *states.State, schemas *t
259259
} else {
260260
newVal = cty.NullVal(ty)
261261
}
262+
263+
if oldVal.RawEquals(newVal) {
264+
// No drift if the two values are semantically equivalent
265+
continue
266+
}
267+
262268
oldSensitive := jsonstate.SensitiveAsBool(oldVal)
263269
newSensitive := jsonstate.SensitiveAsBool(newVal)
264270
oldVal, _ = oldVal.UnmarkDeep()
@@ -290,6 +296,7 @@ func (p *plan) marshalResourceDrift(oldState, newState *states.State, schemas *t
290296
}
291297

292298
change := resourceChange{
299+
Address: addr.String(),
293300
ModuleAddress: addr.Module.String(),
294301
Mode: "managed", // drift reporting is only for managed resources
295302
Name: addr.Resource.Resource.Name,

internal/command/show_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,20 @@ func showFixtureSensitiveSchema() *providers.GetProviderSchemaResponse {
636636
func showFixtureProvider() *terraform.MockProvider {
637637
p := testProvider()
638638
p.GetProviderSchemaResponse = showFixtureSchema()
639+
p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse {
640+
idVal := req.PriorState.GetAttr("id")
641+
amiVal := req.PriorState.GetAttr("ami")
642+
if amiVal.RawEquals(cty.StringVal("refresh-me")) {
643+
amiVal = cty.StringVal("refreshed")
644+
}
645+
return providers.ReadResourceResponse{
646+
NewState: cty.ObjectVal(map[string]cty.Value{
647+
"id": idVal,
648+
"ami": amiVal,
649+
}),
650+
Private: req.Private,
651+
}
652+
}
639653
p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
640654
idVal := req.ProposedNewState.GetAttr("id")
641655
amiVal := req.ProposedNewState.GetAttr("ami")
@@ -758,6 +772,7 @@ type plan struct {
758772
FormatVersion string `json:"format_version,omitempty"`
759773
Variables map[string]interface{} `json:"variables,omitempty"`
760774
PlannedValues map[string]interface{} `json:"planned_values,omitempty"`
775+
ResourceDrift []interface{} `json:"resource_drift,omitempty"`
761776
ResourceChanges []interface{} `json:"resource_changes,omitempty"`
762777
OutputChanges map[string]interface{} `json:"output_changes,omitempty"`
763778
PriorState priorState `json:"prior_state,omitempty"`
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# In state with `ami = "foo"`, so this should be a regular update. The provider
2+
# should not detect changes on refresh.
3+
resource "test_instance" "no_refresh" {
4+
ami = "bar"
5+
}
6+
7+
# In state with `ami = "refresh-me"`, but the provider will return
8+
# `"refreshed"` after the refresh phase. The plan should show the drift
9+
# (`"refresh-me"` to `"refreshed"`) and plan the update (`"refreshed"` to
10+
# `"baz"`).
11+
resource "test_instance" "should_refresh" {
12+
ami = "baz"
13+
}
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
{
2+
"format_version": "0.2",
3+
"planned_values": {
4+
"root_module": {
5+
"resources": [
6+
{
7+
"address": "test_instance.no_refresh",
8+
"mode": "managed",
9+
"type": "test_instance",
10+
"name": "no_refresh",
11+
"provider_name": "registry.terraform.io/hashicorp/test",
12+
"schema_version": 0,
13+
"values": {
14+
"ami": "bar",
15+
"id": "placeholder"
16+
},
17+
"sensitive_values": {}
18+
},
19+
{
20+
"address": "test_instance.should_refresh",
21+
"mode": "managed",
22+
"type": "test_instance",
23+
"name": "should_refresh",
24+
"provider_name": "registry.terraform.io/hashicorp/test",
25+
"schema_version": 0,
26+
"values": {
27+
"ami": "baz",
28+
"id": "placeholder"
29+
},
30+
"sensitive_values": {}
31+
}
32+
]
33+
}
34+
},
35+
"resource_drift": [
36+
{
37+
"address": "test_instance.should_refresh",
38+
"mode": "managed",
39+
"type": "test_instance",
40+
"provider_name": "registry.terraform.io/hashicorp/test",
41+
"name": "should_refresh",
42+
"change": {
43+
"actions": [
44+
"update"
45+
],
46+
"before": {
47+
"ami": "refresh-me",
48+
"id": "placeholder"
49+
},
50+
"after": {
51+
"ami": "refreshed",
52+
"id": "placeholder"
53+
},
54+
"after_sensitive": {},
55+
"before_sensitive": {}
56+
}
57+
}
58+
],
59+
"resource_changes": [
60+
{
61+
"address": "test_instance.no_refresh",
62+
"mode": "managed",
63+
"type": "test_instance",
64+
"provider_name": "registry.terraform.io/hashicorp/test",
65+
"name": "no_refresh",
66+
"change": {
67+
"actions": [
68+
"update"
69+
],
70+
"before": {
71+
"ami": "foo",
72+
"id": "placeholder"
73+
},
74+
"after": {
75+
"ami": "bar",
76+
"id": "placeholder"
77+
},
78+
"after_unknown": {},
79+
"after_sensitive": {},
80+
"before_sensitive": {}
81+
}
82+
},
83+
{
84+
"address": "test_instance.should_refresh",
85+
"mode": "managed",
86+
"type": "test_instance",
87+
"provider_name": "registry.terraform.io/hashicorp/test",
88+
"name": "should_refresh",
89+
"change": {
90+
"actions": [
91+
"update"
92+
],
93+
"before": {
94+
"ami": "refreshed",
95+
"id": "placeholder"
96+
},
97+
"after": {
98+
"ami": "baz",
99+
"id": "placeholder"
100+
},
101+
"after_unknown": {},
102+
"after_sensitive": {},
103+
"before_sensitive": {}
104+
}
105+
}
106+
],
107+
"prior_state": {
108+
"format_version": "0.2",
109+
"values": {
110+
"root_module": {
111+
"resources": [
112+
{
113+
"address": "test_instance.no_refresh",
114+
"mode": "managed",
115+
"type": "test_instance",
116+
"name": "no_refresh",
117+
"schema_version": 0,
118+
"provider_name": "registry.terraform.io/hashicorp/test",
119+
"values": {
120+
"ami": "foo",
121+
"id": "placeholder"
122+
},
123+
"sensitive_values": {}
124+
},
125+
{
126+
"address": "test_instance.should_refresh",
127+
"mode": "managed",
128+
"type": "test_instance",
129+
"name": "should_refresh",
130+
"schema_version": 0,
131+
"provider_name": "registry.terraform.io/hashicorp/test",
132+
"values": {
133+
"ami": "refreshed",
134+
"id": "placeholder"
135+
},
136+
"sensitive_values": {}
137+
}
138+
]
139+
}
140+
}
141+
},
142+
"configuration": {
143+
"root_module": {
144+
"resources": [
145+
{
146+
"address": "test_instance.no_refresh",
147+
"mode": "managed",
148+
"type": "test_instance",
149+
"name": "no_refresh",
150+
"provider_config_key": "test",
151+
"schema_version": 0,
152+
"expressions": {
153+
"ami": {
154+
"constant_value": "bar"
155+
}
156+
}
157+
},
158+
{
159+
"address": "test_instance.should_refresh",
160+
"mode": "managed",
161+
"type": "test_instance",
162+
"name": "should_refresh",
163+
"provider_config_key": "test",
164+
"schema_version": 0,
165+
"expressions": {
166+
"ami": {
167+
"constant_value": "baz"
168+
}
169+
}
170+
}
171+
]
172+
}
173+
}
174+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"version": 4,
3+
"terraform_version": "0.12.0",
4+
"serial": 7,
5+
"lineage": "configuredUnchanged",
6+
"resources": [
7+
{
8+
"mode": "managed",
9+
"type": "test_instance",
10+
"name": "no_refresh",
11+
"provider": "provider[\"registry.terraform.io/hashicorp/test\"]",
12+
"instances": [
13+
{
14+
"schema_version": 0,
15+
"attributes": {
16+
"ami": "foo",
17+
"id": "placeholder"
18+
}
19+
}
20+
]
21+
},
22+
{
23+
"mode": "managed",
24+
"type": "test_instance",
25+
"name": "should_refresh",
26+
"provider": "provider[\"registry.terraform.io/hashicorp/test\"]",
27+
"instances": [
28+
{
29+
"schema_version": 0,
30+
"attributes": {
31+
"ami": "refresh-me",
32+
"id": "placeholder"
33+
}
34+
}
35+
]
36+
}
37+
]
38+
}

internal/command/testdata/show-json/multi-resource-update/output.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,27 @@
4545
]
4646
}
4747
},
48+
"resource_drift": [
49+
{
50+
"address": "test_instance.test",
51+
"mode": "managed",
52+
"type": "test_instance",
53+
"provider_name": "registry.terraform.io/hashicorp/test",
54+
"name": "test",
55+
"change": {
56+
"actions": [
57+
"delete"
58+
],
59+
"before": {
60+
"ami": "bar",
61+
"id": "placeholder"
62+
},
63+
"after": null,
64+
"before_sensitive": {},
65+
"after_sensitive": false
66+
}
67+
}
68+
],
4869
"resource_changes": [
4970
{
5071
"address": "test_instance.test[0]",

0 commit comments

Comments
 (0)