Skip to content

Commit

Permalink
Merge pull request hashicorp#27885 from hashicorp/jbardin/show-json
Browse files Browse the repository at this point in the history
jsonstate: indicate schema version mismatch during encoding
  • Loading branch information
jbardin authored Feb 23, 2021
2 parents 5f3fb00 + c7995b7 commit c103242
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 47 deletions.
6 changes: 5 additions & 1 deletion command/jsonstate/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,14 +300,18 @@ func marshalResources(resources map[string]*states.Resource, module addrs.Module
)
}

schema, _ := schemas.ResourceTypeConfig(
schema, version := schemas.ResourceTypeConfig(
r.ProviderConfig.Provider,
resAddr.Mode,
resAddr.Type,
)

// It is possible that the only instance is deposed
if ri.Current != nil {
if version != ri.Current.SchemaVersion {
return nil, fmt.Errorf("schema version %d for %s in state does not match version %d from the provider", ri.Current.SchemaVersion, resAddr, version)
}

current.SchemaVersion = ri.Current.SchemaVersion

if schema == nil {
Expand Down
111 changes: 65 additions & 46 deletions command/jsonstate/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,8 @@ func TestMarshalResources(t *testing.T) {
Instances: map[addrs.InstanceKey]*states.ResourceInstance{
addrs.NoKey: {
Current: &states.ResourceInstanceObjectSrc{
SchemaVersion: 1,
Status: states.ObjectReady,
AttrsJSON: []byte(`{"woozles":"confuzles"}`),
Status: states.ObjectReady,
AttrsJSON: []byte(`{"woozles":"confuzles"}`),
},
},
},
Expand All @@ -182,13 +181,12 @@ func TestMarshalResources(t *testing.T) {
testSchemas(),
[]resource{
resource{
Address: "test_thing.bar",
Mode: "managed",
Type: "test_thing",
Name: "bar",
Index: addrs.InstanceKey(nil),
ProviderName: "registry.terraform.io/hashicorp/test",
SchemaVersion: 1,
Address: "test_thing.bar",
Mode: "managed",
Type: "test_thing",
Name: "bar",
Index: addrs.InstanceKey(nil),
ProviderName: "registry.terraform.io/hashicorp/test",
AttributeValues: attributeValues{
"foozles": json.RawMessage(`null`),
"woozles": json.RawMessage(`"confuzles"`),
Expand All @@ -197,6 +195,35 @@ func TestMarshalResources(t *testing.T) {
},
false,
},
"single resource wrong schema": {
map[string]*states.Resource{
"test_thing.baz": {
Addr: addrs.AbsResource{
Resource: addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "test_thing",
Name: "bar",
},
},
Instances: map[addrs.InstanceKey]*states.ResourceInstance{
addrs.NoKey: {
Current: &states.ResourceInstanceObjectSrc{
SchemaVersion: 1,
Status: states.ObjectReady,
AttrsJSON: []byte(`{"woozles":["confuzles"]}`),
},
},
},
ProviderConfig: addrs.AbsProviderConfig{
Provider: addrs.NewDefaultProvider("test"),
Module: addrs.RootModule,
},
},
},
testSchemas(),
nil,
true,
},
"resource with count": {
map[string]*states.Resource{
"test_thing.bar": {
Expand All @@ -210,9 +237,8 @@ func TestMarshalResources(t *testing.T) {
Instances: map[addrs.InstanceKey]*states.ResourceInstance{
addrs.IntKey(0): {
Current: &states.ResourceInstanceObjectSrc{
SchemaVersion: 1,
Status: states.ObjectReady,
AttrsJSON: []byte(`{"woozles":"confuzles"}`),
Status: states.ObjectReady,
AttrsJSON: []byte(`{"woozles":"confuzles"}`),
},
},
},
Expand All @@ -225,13 +251,12 @@ func TestMarshalResources(t *testing.T) {
testSchemas(),
[]resource{
resource{
Address: "test_thing.bar[0]",
Mode: "managed",
Type: "test_thing",
Name: "bar",
Index: addrs.IntKey(0),
ProviderName: "registry.terraform.io/hashicorp/test",
SchemaVersion: 1,
Address: "test_thing.bar[0]",
Mode: "managed",
Type: "test_thing",
Name: "bar",
Index: addrs.IntKey(0),
ProviderName: "registry.terraform.io/hashicorp/test",
AttributeValues: attributeValues{
"foozles": json.RawMessage(`null`),
"woozles": json.RawMessage(`"confuzles"`),
Expand All @@ -253,9 +278,8 @@ func TestMarshalResources(t *testing.T) {
Instances: map[addrs.InstanceKey]*states.ResourceInstance{
addrs.StringKey("rockhopper"): {
Current: &states.ResourceInstanceObjectSrc{
SchemaVersion: 1,
Status: states.ObjectReady,
AttrsJSON: []byte(`{"woozles":"confuzles"}`),
Status: states.ObjectReady,
AttrsJSON: []byte(`{"woozles":"confuzles"}`),
},
},
},
Expand All @@ -268,13 +292,12 @@ func TestMarshalResources(t *testing.T) {
testSchemas(),
[]resource{
resource{
Address: "test_thing.bar[\"rockhopper\"]",
Mode: "managed",
Type: "test_thing",
Name: "bar",
Index: addrs.StringKey("rockhopper"),
ProviderName: "registry.terraform.io/hashicorp/test",
SchemaVersion: 1,
Address: "test_thing.bar[\"rockhopper\"]",
Mode: "managed",
Type: "test_thing",
Name: "bar",
Index: addrs.StringKey("rockhopper"),
ProviderName: "registry.terraform.io/hashicorp/test",
AttributeValues: attributeValues{
"foozles": json.RawMessage(`null`),
"woozles": json.RawMessage(`"confuzles"`),
Expand All @@ -297,9 +320,8 @@ func TestMarshalResources(t *testing.T) {
addrs.NoKey: {
Deposed: map[states.DeposedKey]*states.ResourceInstanceObjectSrc{
states.DeposedKey(deposedKey): &states.ResourceInstanceObjectSrc{
SchemaVersion: 1,
Status: states.ObjectReady,
AttrsJSON: []byte(`{"woozles":"confuzles"}`),
Status: states.ObjectReady,
AttrsJSON: []byte(`{"woozles":"confuzles"}`),
},
},
},
Expand Down Expand Up @@ -342,15 +364,13 @@ func TestMarshalResources(t *testing.T) {
addrs.NoKey: {
Deposed: map[states.DeposedKey]*states.ResourceInstanceObjectSrc{
states.DeposedKey(deposedKey): &states.ResourceInstanceObjectSrc{
SchemaVersion: 1,
Status: states.ObjectReady,
AttrsJSON: []byte(`{"woozles":"confuzles"}`),
Status: states.ObjectReady,
AttrsJSON: []byte(`{"woozles":"confuzles"}`),
},
},
Current: &states.ResourceInstanceObjectSrc{
SchemaVersion: 1,
Status: states.ObjectReady,
AttrsJSON: []byte(`{"woozles":"confuzles"}`),
Status: states.ObjectReady,
AttrsJSON: []byte(`{"woozles":"confuzles"}`),
},
},
},
Expand All @@ -363,13 +383,12 @@ func TestMarshalResources(t *testing.T) {
testSchemas(),
[]resource{
resource{
Address: "test_thing.bar",
Mode: "managed",
Type: "test_thing",
Name: "bar",
Index: addrs.InstanceKey(nil),
ProviderName: "registry.terraform.io/hashicorp/test",
SchemaVersion: 1,
Address: "test_thing.bar",
Mode: "managed",
Type: "test_thing",
Name: "bar",
Index: addrs.InstanceKey(nil),
ProviderName: "registry.terraform.io/hashicorp/test",
AttributeValues: attributeValues{
"foozles": json.RawMessage(`null`),
"woozles": json.RawMessage(`"confuzles"`),
Expand Down
6 changes: 6 additions & 0 deletions website/docs/cli/commands/show.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ For Terraform state files (including when no path is provided),
For Terraform plan files, `terraform show -json` will show a JSON representation
of the plan, configuration, and current state.

If you've updated providers which contain new schema versions since the state
was written, the state needs to be upgraded before it can be displayed with
`show -json`. If you are viewing a plan, it must be created without
`-refresh=false`. If you are viewing a state file, run `terraform refresh`
first.

The output format is covered in detail in [JSON Output Format](/docs/internals/json-format.html).

## Usage
Expand Down

0 comments on commit c103242

Please sign in to comment.