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.
This commit is contained in:
parent
af68a1e55a
commit
3326ab7dae
|
@ -259,6 +259,12 @@ func (p *plan) marshalResourceDrift(oldState, newState *states.State, schemas *t
|
||||||
} else {
|
} else {
|
||||||
newVal = cty.NullVal(ty)
|
newVal = cty.NullVal(ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if oldVal.RawEquals(newVal) {
|
||||||
|
// No drift if the two values are semantically equivalent
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
oldSensitive := jsonstate.SensitiveAsBool(oldVal)
|
oldSensitive := jsonstate.SensitiveAsBool(oldVal)
|
||||||
newSensitive := jsonstate.SensitiveAsBool(newVal)
|
newSensitive := jsonstate.SensitiveAsBool(newVal)
|
||||||
oldVal, _ = oldVal.UnmarkDeep()
|
oldVal, _ = oldVal.UnmarkDeep()
|
||||||
|
@ -290,6 +296,7 @@ func (p *plan) marshalResourceDrift(oldState, newState *states.State, schemas *t
|
||||||
}
|
}
|
||||||
|
|
||||||
change := resourceChange{
|
change := resourceChange{
|
||||||
|
Address: addr.String(),
|
||||||
ModuleAddress: addr.Module.String(),
|
ModuleAddress: addr.Module.String(),
|
||||||
Mode: "managed", // drift reporting is only for managed resources
|
Mode: "managed", // drift reporting is only for managed resources
|
||||||
Name: addr.Resource.Resource.Name,
|
Name: addr.Resource.Resource.Name,
|
||||||
|
|
|
@ -636,6 +636,20 @@ func showFixtureSensitiveSchema() *providers.GetProviderSchemaResponse {
|
||||||
func showFixtureProvider() *terraform.MockProvider {
|
func showFixtureProvider() *terraform.MockProvider {
|
||||||
p := testProvider()
|
p := testProvider()
|
||||||
p.GetProviderSchemaResponse = showFixtureSchema()
|
p.GetProviderSchemaResponse = showFixtureSchema()
|
||||||
|
p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse {
|
||||||
|
idVal := req.PriorState.GetAttr("id")
|
||||||
|
amiVal := req.PriorState.GetAttr("ami")
|
||||||
|
if amiVal.RawEquals(cty.StringVal("refresh-me")) {
|
||||||
|
amiVal = cty.StringVal("refreshed")
|
||||||
|
}
|
||||||
|
return providers.ReadResourceResponse{
|
||||||
|
NewState: cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"id": idVal,
|
||||||
|
"ami": amiVal,
|
||||||
|
}),
|
||||||
|
Private: req.Private,
|
||||||
|
}
|
||||||
|
}
|
||||||
p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
|
p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
|
||||||
idVal := req.ProposedNewState.GetAttr("id")
|
idVal := req.ProposedNewState.GetAttr("id")
|
||||||
amiVal := req.ProposedNewState.GetAttr("ami")
|
amiVal := req.ProposedNewState.GetAttr("ami")
|
||||||
|
@ -758,6 +772,7 @@ type plan struct {
|
||||||
FormatVersion string `json:"format_version,omitempty"`
|
FormatVersion string `json:"format_version,omitempty"`
|
||||||
Variables map[string]interface{} `json:"variables,omitempty"`
|
Variables map[string]interface{} `json:"variables,omitempty"`
|
||||||
PlannedValues map[string]interface{} `json:"planned_values,omitempty"`
|
PlannedValues map[string]interface{} `json:"planned_values,omitempty"`
|
||||||
|
ResourceDrift []interface{} `json:"resource_drift,omitempty"`
|
||||||
ResourceChanges []interface{} `json:"resource_changes,omitempty"`
|
ResourceChanges []interface{} `json:"resource_changes,omitempty"`
|
||||||
OutputChanges map[string]interface{} `json:"output_changes,omitempty"`
|
OutputChanges map[string]interface{} `json:"output_changes,omitempty"`
|
||||||
PriorState priorState `json:"prior_state,omitempty"`
|
PriorState priorState `json:"prior_state,omitempty"`
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
# In state with `ami = "foo"`, so this should be a regular update. The provider
|
||||||
|
# should not detect changes on refresh.
|
||||||
|
resource "test_instance" "no_refresh" {
|
||||||
|
ami = "bar"
|
||||||
|
}
|
||||||
|
|
||||||
|
# In state with `ami = "refresh-me"`, but the provider will return
|
||||||
|
# `"refreshed"` after the refresh phase. The plan should show the drift
|
||||||
|
# (`"refresh-me"` to `"refreshed"`) and plan the update (`"refreshed"` to
|
||||||
|
# `"baz"`).
|
||||||
|
resource "test_instance" "should_refresh" {
|
||||||
|
ami = "baz"
|
||||||
|
}
|
|
@ -0,0 +1,174 @@
|
||||||
|
{
|
||||||
|
"format_version": "0.2",
|
||||||
|
"planned_values": {
|
||||||
|
"root_module": {
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"address": "test_instance.no_refresh",
|
||||||
|
"mode": "managed",
|
||||||
|
"type": "test_instance",
|
||||||
|
"name": "no_refresh",
|
||||||
|
"provider_name": "registry.terraform.io/hashicorp/test",
|
||||||
|
"schema_version": 0,
|
||||||
|
"values": {
|
||||||
|
"ami": "bar",
|
||||||
|
"id": "placeholder"
|
||||||
|
},
|
||||||
|
"sensitive_values": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "test_instance.should_refresh",
|
||||||
|
"mode": "managed",
|
||||||
|
"type": "test_instance",
|
||||||
|
"name": "should_refresh",
|
||||||
|
"provider_name": "registry.terraform.io/hashicorp/test",
|
||||||
|
"schema_version": 0,
|
||||||
|
"values": {
|
||||||
|
"ami": "baz",
|
||||||
|
"id": "placeholder"
|
||||||
|
},
|
||||||
|
"sensitive_values": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"resource_drift": [
|
||||||
|
{
|
||||||
|
"address": "test_instance.should_refresh",
|
||||||
|
"mode": "managed",
|
||||||
|
"type": "test_instance",
|
||||||
|
"provider_name": "registry.terraform.io/hashicorp/test",
|
||||||
|
"name": "should_refresh",
|
||||||
|
"change": {
|
||||||
|
"actions": [
|
||||||
|
"update"
|
||||||
|
],
|
||||||
|
"before": {
|
||||||
|
"ami": "refresh-me",
|
||||||
|
"id": "placeholder"
|
||||||
|
},
|
||||||
|
"after": {
|
||||||
|
"ami": "refreshed",
|
||||||
|
"id": "placeholder"
|
||||||
|
},
|
||||||
|
"after_sensitive": {},
|
||||||
|
"before_sensitive": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"resource_changes": [
|
||||||
|
{
|
||||||
|
"address": "test_instance.no_refresh",
|
||||||
|
"mode": "managed",
|
||||||
|
"type": "test_instance",
|
||||||
|
"provider_name": "registry.terraform.io/hashicorp/test",
|
||||||
|
"name": "no_refresh",
|
||||||
|
"change": {
|
||||||
|
"actions": [
|
||||||
|
"update"
|
||||||
|
],
|
||||||
|
"before": {
|
||||||
|
"ami": "foo",
|
||||||
|
"id": "placeholder"
|
||||||
|
},
|
||||||
|
"after": {
|
||||||
|
"ami": "bar",
|
||||||
|
"id": "placeholder"
|
||||||
|
},
|
||||||
|
"after_unknown": {},
|
||||||
|
"after_sensitive": {},
|
||||||
|
"before_sensitive": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "test_instance.should_refresh",
|
||||||
|
"mode": "managed",
|
||||||
|
"type": "test_instance",
|
||||||
|
"provider_name": "registry.terraform.io/hashicorp/test",
|
||||||
|
"name": "should_refresh",
|
||||||
|
"change": {
|
||||||
|
"actions": [
|
||||||
|
"update"
|
||||||
|
],
|
||||||
|
"before": {
|
||||||
|
"ami": "refreshed",
|
||||||
|
"id": "placeholder"
|
||||||
|
},
|
||||||
|
"after": {
|
||||||
|
"ami": "baz",
|
||||||
|
"id": "placeholder"
|
||||||
|
},
|
||||||
|
"after_unknown": {},
|
||||||
|
"after_sensitive": {},
|
||||||
|
"before_sensitive": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"prior_state": {
|
||||||
|
"format_version": "0.2",
|
||||||
|
"values": {
|
||||||
|
"root_module": {
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"address": "test_instance.no_refresh",
|
||||||
|
"mode": "managed",
|
||||||
|
"type": "test_instance",
|
||||||
|
"name": "no_refresh",
|
||||||
|
"schema_version": 0,
|
||||||
|
"provider_name": "registry.terraform.io/hashicorp/test",
|
||||||
|
"values": {
|
||||||
|
"ami": "foo",
|
||||||
|
"id": "placeholder"
|
||||||
|
},
|
||||||
|
"sensitive_values": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "test_instance.should_refresh",
|
||||||
|
"mode": "managed",
|
||||||
|
"type": "test_instance",
|
||||||
|
"name": "should_refresh",
|
||||||
|
"schema_version": 0,
|
||||||
|
"provider_name": "registry.terraform.io/hashicorp/test",
|
||||||
|
"values": {
|
||||||
|
"ami": "refreshed",
|
||||||
|
"id": "placeholder"
|
||||||
|
},
|
||||||
|
"sensitive_values": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"configuration": {
|
||||||
|
"root_module": {
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"address": "test_instance.no_refresh",
|
||||||
|
"mode": "managed",
|
||||||
|
"type": "test_instance",
|
||||||
|
"name": "no_refresh",
|
||||||
|
"provider_config_key": "test",
|
||||||
|
"schema_version": 0,
|
||||||
|
"expressions": {
|
||||||
|
"ami": {
|
||||||
|
"constant_value": "bar"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "test_instance.should_refresh",
|
||||||
|
"mode": "managed",
|
||||||
|
"type": "test_instance",
|
||||||
|
"name": "should_refresh",
|
||||||
|
"provider_config_key": "test",
|
||||||
|
"schema_version": 0,
|
||||||
|
"expressions": {
|
||||||
|
"ami": {
|
||||||
|
"constant_value": "baz"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"version": 4,
|
||||||
|
"terraform_version": "0.12.0",
|
||||||
|
"serial": 7,
|
||||||
|
"lineage": "configuredUnchanged",
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"mode": "managed",
|
||||||
|
"type": "test_instance",
|
||||||
|
"name": "no_refresh",
|
||||||
|
"provider": "provider[\"registry.terraform.io/hashicorp/test\"]",
|
||||||
|
"instances": [
|
||||||
|
{
|
||||||
|
"schema_version": 0,
|
||||||
|
"attributes": {
|
||||||
|
"ami": "foo",
|
||||||
|
"id": "placeholder"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mode": "managed",
|
||||||
|
"type": "test_instance",
|
||||||
|
"name": "should_refresh",
|
||||||
|
"provider": "provider[\"registry.terraform.io/hashicorp/test\"]",
|
||||||
|
"instances": [
|
||||||
|
{
|
||||||
|
"schema_version": 0,
|
||||||
|
"attributes": {
|
||||||
|
"ami": "refresh-me",
|
||||||
|
"id": "placeholder"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -45,6 +45,27 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"resource_drift": [
|
||||||
|
{
|
||||||
|
"address": "test_instance.test",
|
||||||
|
"mode": "managed",
|
||||||
|
"type": "test_instance",
|
||||||
|
"provider_name": "registry.terraform.io/hashicorp/test",
|
||||||
|
"name": "test",
|
||||||
|
"change": {
|
||||||
|
"actions": [
|
||||||
|
"delete"
|
||||||
|
],
|
||||||
|
"before": {
|
||||||
|
"ami": "bar",
|
||||||
|
"id": "placeholder"
|
||||||
|
},
|
||||||
|
"after": null,
|
||||||
|
"before_sensitive": {},
|
||||||
|
"after_sensitive": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
"resource_changes": [
|
"resource_changes": [
|
||||||
{
|
{
|
||||||
"address": "test_instance.test[0]",
|
"address": "test_instance.test[0]",
|
||||||
|
|
Loading…
Reference in New Issue