jsonstate: sort child modules by address for consistency (#24329)

* jsonstate: sort child modules by address for consistency
This commit is contained in:
Kristin Laemmert 2020-03-09 15:57:14 -04:00 committed by GitHub
parent ff3895ea26
commit add16fc67b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 173 additions and 19 deletions

View File

@ -212,8 +212,8 @@ func marshalRootModule(s *states.State, schemas *terraform.Schemas) (module, err
return ret, err return ret, err
} }
// marshalModules is an ungainly recursive function to build a module // marshalModules is an ungainly recursive function to build a module structure
// structure out of a teraform state. // out of terraform state.
func marshalModules( func marshalModules(
s *states.State, s *states.State,
schemas *terraform.Schemas, schemas *terraform.Schemas,
@ -241,6 +241,11 @@ func marshalModules(
ret = append(ret, cm) ret = append(ret, cm)
} }
// sort the child modules by address for consistency.
sort.Slice(ret, func(i, j int) bool {
return ret[i].Address < ret[j].Address
})
return ret, nil return ret, nil
} }

View File

@ -436,6 +436,148 @@ func TestMarshalResources(t *testing.T) {
} }
} }
func TestMarshalModules_basic(t *testing.T) {
childModule, _ := addrs.ParseModuleInstanceStr("module.child")
subModule, _ := addrs.ParseModuleInstanceStr("module.submodule")
testState := states.BuildState(func(s *states.SyncState) {
s.SetResourceInstanceCurrent(
addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "test_instance",
Name: "foo",
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
&states.ResourceInstanceObjectSrc{
AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
Status: states.ObjectReady,
},
addrs.AbsProviderConfig{
Provider: addrs.NewLegacyProvider("test"),
Module: addrs.RootModuleInstance,
},
)
s.SetResourceInstanceCurrent(
addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "test_instance",
Name: "foo",
}.Instance(addrs.NoKey).Absolute(childModule),
&states.ResourceInstanceObjectSrc{
AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`),
Status: states.ObjectReady,
},
addrs.AbsProviderConfig{
Provider: addrs.NewLegacyProvider("test"),
Module: childModule,
},
)
s.SetResourceInstanceCurrent(
addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "test_instance",
Name: "foo",
}.Instance(addrs.NoKey).Absolute(subModule),
&states.ResourceInstanceObjectSrc{
AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`),
Status: states.ObjectReady,
},
addrs.AbsProviderConfig{
Provider: addrs.NewLegacyProvider("test"),
Module: subModule,
},
)
})
moduleMap := make(map[string][]addrs.ModuleInstance)
moduleMap[""] = []addrs.ModuleInstance{childModule, subModule}
got, err := marshalModules(testState, testSchemas(), moduleMap[""], moduleMap)
if err != nil {
t.Fatalf("unexpected error: %s", err.Error())
}
if len(got) != 2 {
t.Fatalf("wrong result! got %d modules, expected 2", len(got))
}
if got[0].Address != "module.child" || got[1].Address != "module.submodule" {
t.Fatalf("wrong result! got %#v\n", got)
}
}
func TestMarshalModules_nested(t *testing.T) {
childModule, _ := addrs.ParseModuleInstanceStr("module.child")
subModule, _ := addrs.ParseModuleInstanceStr("module.child.module.submodule")
testState := states.BuildState(func(s *states.SyncState) {
s.SetResourceInstanceCurrent(
addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "test_instance",
Name: "foo",
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
&states.ResourceInstanceObjectSrc{
AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`),
Status: states.ObjectReady,
},
addrs.AbsProviderConfig{
Provider: addrs.NewLegacyProvider("test"),
Module: addrs.RootModuleInstance,
},
)
s.SetResourceInstanceCurrent(
addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "test_instance",
Name: "foo",
}.Instance(addrs.NoKey).Absolute(childModule),
&states.ResourceInstanceObjectSrc{
AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`),
Status: states.ObjectReady,
},
addrs.AbsProviderConfig{
Provider: addrs.NewLegacyProvider("test"),
Module: childModule,
},
)
s.SetResourceInstanceCurrent(
addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "test_instance",
Name: "foo",
}.Instance(addrs.NoKey).Absolute(subModule),
&states.ResourceInstanceObjectSrc{
AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`),
Status: states.ObjectReady,
},
addrs.AbsProviderConfig{
Provider: addrs.NewLegacyProvider("test"),
Module: subModule,
},
)
})
moduleMap := make(map[string][]addrs.ModuleInstance)
moduleMap[""] = []addrs.ModuleInstance{childModule}
moduleMap[childModule.String()] = []addrs.ModuleInstance{subModule}
got, err := marshalModules(testState, testSchemas(), moduleMap[""], moduleMap)
if err != nil {
t.Fatalf("unexpected error: %s", err.Error())
}
if len(got) != 1 {
t.Fatalf("wrong result! got %d modules, expected 1", len(got))
}
if got[0].Address != "module.child" {
t.Fatalf("wrong result! got %#v\n", got)
}
if got[0].ChildModules[0].Address != "module.child.module.submodule" {
t.Fatalf("wrong result! got %#v\n", got)
}
}
func testSchemas() *terraform.Schemas { func testSchemas() *terraform.Schemas {
return &terraform.Schemas{ return &terraform.Schemas{
Providers: map[addrs.Provider]*terraform.ProviderSchema{ Providers: map[addrs.Provider]*terraform.ProviderSchema{
@ -447,6 +589,13 @@ func testSchemas() *terraform.Schemas {
"foozles": {Type: cty.String, Optional: true}, "foozles": {Type: cty.String, Optional: true},
}, },
}, },
"test_instance": {
Attributes: map[string]*configschema.Attribute{
"id": {Type: cty.String, Optional: true, Computed: true},
"foo": {Type: cty.String, Optional: true},
"bar": {Type: cty.String, Optional: true},
},
},
}, },
}, },
}, },

View File

@ -10,6 +10,23 @@
}, },
"root_module": { "root_module": {
"child_modules": [ "child_modules": [
{
"resources": [
{
"address": "module.module_test_bar.test_instance.example",
"mode": "managed",
"type": "test_instance",
"name": "example",
"provider_name": "test",
"schema_version": 0,
"values": {
"ami": "bar-var",
"id": null
}
}
],
"address": "module.module_test_bar"
},
{ {
"resources": [ "resources": [
{ {
@ -27,23 +44,6 @@
} }
], ],
"address": "module.module_test_foo" "address": "module.module_test_foo"
},
{
"resources": [
{
"address": "module.module_test_bar.test_instance.example",
"mode": "managed",
"type": "test_instance",
"name": "example",
"provider_name": "test",
"schema_version": 0,
"values": {
"ami": "bar-var",
"id": null
}
}
],
"address": "module.module_test_bar"
} }
] ]
} }