github.com/hashicorp/terraform-plugin-sdk@v1.17.2/helper/resource/state_shim_test.go (about) 1 package resource 2 3 import ( 4 "testing" 5 6 "github.com/hashicorp/terraform-plugin-sdk/helper/schema" 7 "github.com/hashicorp/terraform-plugin-sdk/internal/addrs" 8 "github.com/hashicorp/terraform-plugin-sdk/internal/states" 9 "github.com/hashicorp/terraform-plugin-sdk/terraform" 10 "github.com/zclconf/go-cty/cty" 11 ) 12 13 // TestStateShim is meant to be a fairly comprehensive test, checking for dependencies, root outputs, 14 func TestStateShim(t *testing.T) { 15 state := states.NewState() 16 17 rootModule := state.RootModule() 18 if rootModule == nil { 19 t.Errorf("root module is nil; want valid object") 20 } 21 22 rootModule.SetOutputValue("bar", cty.ListVal([]cty.Value{cty.StringVal("bar"), cty.StringVal("value")}), false) 23 rootModule.SetOutputValue("secret", cty.StringVal("secret value"), true) 24 rootModule.SetResourceInstanceCurrent( 25 addrs.Resource{ 26 Mode: addrs.ManagedResourceMode, 27 Type: "test_thing", 28 Name: "foo", 29 }.Instance(addrs.NoKey), 30 &states.ResourceInstanceObjectSrc{ 31 Status: states.ObjectReady, 32 AttrsFlat: map[string]string{"id": "foo", "bazzle": "dazzle"}, 33 SchemaVersion: 7, 34 Dependencies: []addrs.Referenceable{ 35 addrs.ResourceInstance{ 36 Resource: addrs.Resource{ 37 Mode: 'M', 38 Type: "test_thing", 39 Name: "baz", 40 }, 41 }, 42 }, 43 }, 44 addrs.ProviderConfig{ 45 Type: "test", 46 }.Absolute(addrs.RootModuleInstance), 47 ) 48 rootModule.SetResourceInstanceCurrent( 49 addrs.Resource{ 50 Mode: addrs.ManagedResourceMode, 51 Type: "test_thing", 52 Name: "baz", 53 }.Instance(addrs.NoKey), 54 &states.ResourceInstanceObjectSrc{ 55 Status: states.ObjectReady, 56 AttrsFlat: map[string]string{"id": "baz", "bazzle": "dazzle"}, 57 Dependencies: []addrs.Referenceable{}, 58 }, 59 addrs.ProviderConfig{ 60 Type: "test", 61 }.Absolute(addrs.RootModuleInstance), 62 ) 63 64 childInstance := addrs.RootModuleInstance.Child("child", addrs.NoKey) 65 childModule := state.EnsureModule(childInstance) 66 childModule.SetResourceInstanceCurrent( 67 addrs.Resource{ 68 Mode: addrs.DataResourceMode, 69 Type: "test_data_thing", 70 Name: "foo", 71 }.Instance(addrs.NoKey), 72 &states.ResourceInstanceObjectSrc{ 73 Status: states.ObjectReady, 74 AttrsJSON: []byte(`{"id": "bar", "fuzzle":"wuzzle"}`), 75 Dependencies: []addrs.Referenceable{}, 76 }, 77 addrs.ProviderConfig{ 78 Type: "test", 79 }.Absolute(childInstance), 80 ) 81 childModule.SetResourceInstanceCurrent( 82 addrs.Resource{ 83 Mode: addrs.ManagedResourceMode, 84 Type: "test_thing", 85 Name: "baz", 86 }.Instance(addrs.NoKey), 87 &states.ResourceInstanceObjectSrc{ 88 Status: states.ObjectReady, 89 AttrsJSON: []byte(`{"id": "bar", "fizzle":"wizzle"}`), 90 Dependencies: []addrs.Referenceable{ 91 addrs.ResourceInstance{ 92 Resource: addrs.Resource{ 93 Mode: 'D', 94 Type: "test_data_thing", 95 Name: "foo", 96 }, 97 }, 98 }, 99 }, 100 addrs.ProviderConfig{ 101 Type: "test", 102 }.Absolute(childInstance), 103 ) 104 105 childModule.SetResourceInstanceDeposed( 106 addrs.Resource{ 107 Mode: addrs.ManagedResourceMode, 108 Type: "test_thing", 109 Name: "baz", 110 }.Instance(addrs.NoKey), 111 "00000001", 112 &states.ResourceInstanceObjectSrc{ 113 Status: states.ObjectReady, 114 AttrsFlat: map[string]string{"id": "old", "fizzle": "wizzle"}, 115 Dependencies: []addrs.Referenceable{ 116 addrs.ResourceInstance{ 117 Resource: addrs.Resource{ 118 Mode: 'D', 119 Type: "test_data_thing", 120 Name: "foo", 121 }, 122 }, 123 }, 124 }, 125 addrs.ProviderConfig{ 126 Type: "test", 127 }.Absolute(childInstance), 128 ) 129 130 childModule.SetResourceInstanceCurrent( 131 addrs.Resource{ 132 Mode: addrs.ManagedResourceMode, 133 Type: "test_thing", 134 Name: "lots", 135 }.Instance(addrs.IntKey(0)), 136 &states.ResourceInstanceObjectSrc{ 137 Status: states.ObjectReady, 138 AttrsFlat: map[string]string{"id": "0", "bazzle": "dazzle"}, 139 Dependencies: []addrs.Referenceable{}, 140 }, 141 addrs.ProviderConfig{ 142 Type: "test", 143 }.Absolute(childInstance), 144 ) 145 childModule.SetResourceInstanceCurrent( 146 addrs.Resource{ 147 Mode: addrs.ManagedResourceMode, 148 Type: "test_thing", 149 Name: "lots", 150 }.Instance(addrs.IntKey(1)), 151 &states.ResourceInstanceObjectSrc{ 152 Status: states.ObjectTainted, 153 AttrsFlat: map[string]string{"id": "1", "bazzle": "dazzle"}, 154 Dependencies: []addrs.Referenceable{}, 155 }, 156 addrs.ProviderConfig{ 157 Type: "test", 158 }.Absolute(childInstance), 159 ) 160 161 childModule.SetResourceInstanceCurrent( 162 addrs.Resource{ 163 Mode: addrs.ManagedResourceMode, 164 Type: "test_thing", 165 Name: "single_count", 166 }.Instance(addrs.IntKey(0)), 167 &states.ResourceInstanceObjectSrc{ 168 Status: states.ObjectReady, 169 AttrsJSON: []byte(`{"id": "single", "bazzle":"dazzle"}`), 170 Dependencies: []addrs.Referenceable{}, 171 }, 172 addrs.ProviderConfig{ 173 Type: "test", 174 }.Absolute(childInstance), 175 ) 176 177 expected := &terraform.State{ 178 Version: 3, 179 Modules: []*terraform.ModuleState{ 180 { 181 Path: []string{"root"}, 182 Outputs: map[string]*terraform.OutputState{ 183 "bar": { 184 Type: "list", 185 Value: []interface{}{"bar", "value"}, 186 }, 187 "secret": { 188 Sensitive: true, 189 Type: "string", 190 Value: "secret value", 191 }, 192 }, 193 Resources: map[string]*terraform.ResourceState{ 194 "test_thing.baz": { 195 Type: "test_thing", 196 Provider: "provider.test", 197 Primary: &terraform.InstanceState{ 198 ID: "baz", 199 Attributes: map[string]string{ 200 "id": "baz", 201 "bazzle": "dazzle", 202 }, 203 }, 204 }, 205 "test_thing.foo": { 206 Type: "test_thing", 207 Provider: "provider.test", 208 Primary: &terraform.InstanceState{ 209 ID: "foo", 210 Attributes: map[string]string{ 211 "id": "foo", 212 "bazzle": "dazzle", 213 }, 214 Meta: map[string]interface{}{ 215 "schema_version": 7, 216 }, 217 }, 218 Dependencies: []string{"test_thing.baz"}, 219 }, 220 }, 221 }, 222 { 223 Path: []string{"root", "child"}, 224 Resources: map[string]*terraform.ResourceState{ 225 "test_thing.baz": { 226 Type: "test_thing", 227 Provider: "module.child.provider.test", 228 Primary: &terraform.InstanceState{ 229 ID: "bar", 230 Attributes: map[string]string{ 231 "id": "bar", 232 "fizzle": "wizzle", 233 }, 234 }, 235 Deposed: []*terraform.InstanceState{ 236 { 237 ID: "old", 238 Attributes: map[string]string{ 239 "id": "old", 240 "fizzle": "wizzle", 241 }, 242 }, 243 }, 244 Dependencies: []string{"data.test_data_thing.foo"}, 245 }, 246 "data.test_data_thing.foo": { 247 Type: "test_data_thing", 248 Provider: "module.child.provider.test", 249 Primary: &terraform.InstanceState{ 250 ID: "bar", 251 Attributes: map[string]string{ 252 "id": "bar", 253 "fuzzle": "wuzzle", 254 }, 255 }, 256 }, 257 "test_thing.lots.0": { 258 Type: "test_thing", 259 Provider: "module.child.provider.test", 260 Primary: &terraform.InstanceState{ 261 ID: "0", 262 Attributes: map[string]string{ 263 "id": "0", 264 "bazzle": "dazzle", 265 }, 266 }, 267 }, 268 "test_thing.lots.1": { 269 Type: "test_thing", 270 Provider: "module.child.provider.test", 271 Primary: &terraform.InstanceState{ 272 ID: "1", 273 Attributes: map[string]string{ 274 "id": "1", 275 "bazzle": "dazzle", 276 }, 277 Tainted: true, 278 }, 279 }, 280 "test_thing.single_count": { 281 Type: "test_thing", 282 Provider: "module.child.provider.test", 283 Primary: &terraform.InstanceState{ 284 ID: "single", 285 Attributes: map[string]string{ 286 "id": "single", 287 "bazzle": "dazzle", 288 }, 289 }, 290 }, 291 }, 292 }, 293 }, 294 } 295 296 providers := map[string]terraform.ResourceProvider{ 297 "test": &schema.Provider{ 298 ResourcesMap: map[string]*schema.Resource{ 299 "test_thing": { 300 Schema: map[string]*schema.Schema{ 301 "id": {Type: schema.TypeString, Computed: true}, 302 "fizzle": {Type: schema.TypeString, Optional: true}, 303 "bazzle": {Type: schema.TypeString, Optional: true}, 304 }, 305 }, 306 }, 307 DataSourcesMap: map[string]*schema.Resource{ 308 "test_data_thing": { 309 Schema: map[string]*schema.Schema{ 310 "id": {Type: schema.TypeString, Computed: true}, 311 "fuzzle": {Type: schema.TypeString, Optional: true}, 312 }, 313 }, 314 }, 315 }, 316 } 317 318 shimmed, err := shimNewState(state, providers) 319 if err != nil { 320 t.Fatal(err) 321 } 322 323 if !expected.Equal(shimmed) { 324 t.Fatalf("wrong result state\ngot:\n%s\n\nwant:\n%s", expected, shimmed) 325 } 326 }