Merge pull request #28975 from hashicorp/alisdair/jsonplan-drift

json-output: Omit unchanged resource_drift entries
This commit is contained in:
Alisdair McDiarmid 2021-06-18 11:37:49 -04:00 committed by GitHub
commit 5611da8eb5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 268 additions and 0 deletions

View File

@ -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,

View File

@ -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"`

View File

@ -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"
}

View File

@ -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"
}
}
}
]
}
}
}

View File

@ -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"
}
}
]
}
]
}

View File

@ -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]",