github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/command/format/state_test.go (about) 1 package format 2 3 import ( 4 "fmt" 5 "testing" 6 7 "github.com/hashicorp/terraform/internal/addrs" 8 "github.com/hashicorp/terraform/internal/configs/configschema" 9 "github.com/hashicorp/terraform/internal/providers" 10 "github.com/hashicorp/terraform/internal/states" 11 "github.com/hashicorp/terraform/internal/terraform" 12 "github.com/zclconf/go-cty/cty" 13 ) 14 15 func TestState(t *testing.T) { 16 tests := []struct { 17 State *StateOpts 18 Want string 19 }{ 20 { 21 &StateOpts{ 22 State: &states.State{}, 23 Color: disabledColorize, 24 Schemas: &terraform.Schemas{}, 25 }, 26 "The state file is empty. No resources are represented.", 27 }, 28 { 29 &StateOpts{ 30 State: basicState(t), 31 Color: disabledColorize, 32 Schemas: testSchemas(), 33 }, 34 basicStateOutput, 35 }, 36 { 37 &StateOpts{ 38 State: nestedState(t), 39 Color: disabledColorize, 40 Schemas: testSchemas(), 41 }, 42 nestedStateOutput, 43 }, 44 { 45 &StateOpts{ 46 State: deposedState(t), 47 Color: disabledColorize, 48 Schemas: testSchemas(), 49 }, 50 deposedNestedStateOutput, 51 }, 52 { 53 &StateOpts{ 54 State: onlyDeposedState(t), 55 Color: disabledColorize, 56 Schemas: testSchemas(), 57 }, 58 onlyDeposedOutput, 59 }, 60 { 61 &StateOpts{ 62 State: stateWithMoreOutputs(t), 63 Color: disabledColorize, 64 Schemas: testSchemas(), 65 }, 66 stateWithMoreOutputsOutput, 67 }, 68 } 69 70 for i, tt := range tests { 71 t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { 72 got := State(tt.State) 73 if got != tt.Want { 74 t.Errorf( 75 "wrong result\ninput: %v\ngot: \n%q\nwant: \n%q", 76 tt.State.State, got, tt.Want, 77 ) 78 } 79 }) 80 } 81 } 82 83 func testProvider() *terraform.MockProvider { 84 p := new(terraform.MockProvider) 85 p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse { 86 return providers.ReadResourceResponse{NewState: req.PriorState} 87 } 88 89 p.GetProviderSchemaResponse = testProviderSchema() 90 91 return p 92 } 93 94 func testProviderSchema() *providers.GetProviderSchemaResponse { 95 return &providers.GetProviderSchemaResponse{ 96 Provider: providers.Schema{ 97 Block: &configschema.Block{ 98 Attributes: map[string]*configschema.Attribute{ 99 "region": {Type: cty.String, Optional: true}, 100 }, 101 }, 102 }, 103 ResourceTypes: map[string]providers.Schema{ 104 "test_resource": { 105 Block: &configschema.Block{ 106 Attributes: map[string]*configschema.Attribute{ 107 "id": {Type: cty.String, Computed: true}, 108 "foo": {Type: cty.String, Optional: true}, 109 "woozles": {Type: cty.String, Optional: true}, 110 }, 111 BlockTypes: map[string]*configschema.NestedBlock{ 112 "nested": { 113 Nesting: configschema.NestingList, 114 Block: configschema.Block{ 115 Attributes: map[string]*configschema.Attribute{ 116 "compute": {Type: cty.String, Optional: true}, 117 "value": {Type: cty.String, Optional: true}, 118 }, 119 }, 120 }, 121 }, 122 }, 123 }, 124 }, 125 DataSources: map[string]providers.Schema{ 126 "test_data_source": { 127 Block: &configschema.Block{ 128 Attributes: map[string]*configschema.Attribute{ 129 "compute": {Type: cty.String, Optional: true}, 130 "value": {Type: cty.String, Computed: true}, 131 }, 132 }, 133 }, 134 }, 135 } 136 } 137 138 func testSchemas() *terraform.Schemas { 139 provider := testProvider() 140 return &terraform.Schemas{ 141 Providers: map[addrs.Provider]*terraform.ProviderSchema{ 142 addrs.NewDefaultProvider("test"): provider.ProviderSchema(), 143 }, 144 } 145 } 146 147 const basicStateOutput = `# data.test_data_source.data: 148 data "test_data_source" "data" { 149 compute = "sure" 150 } 151 152 # test_resource.baz[0]: 153 resource "test_resource" "baz" { 154 woozles = "confuzles" 155 } 156 157 158 Outputs: 159 160 bar = "bar value"` 161 162 const nestedStateOutput = `# test_resource.baz[0]: 163 resource "test_resource" "baz" { 164 woozles = "confuzles" 165 166 nested { 167 value = "42" 168 } 169 }` 170 171 const deposedNestedStateOutput = `# test_resource.baz[0]: 172 resource "test_resource" "baz" { 173 woozles = "confuzles" 174 175 nested { 176 value = "42" 177 } 178 } 179 180 # test_resource.baz[0]: (deposed object 1234) 181 resource "test_resource" "baz" { 182 woozles = "confuzles" 183 184 nested { 185 value = "42" 186 } 187 }` 188 189 const onlyDeposedOutput = `# test_resource.baz[0]: 190 # test_resource.baz[0]: (deposed object 1234) 191 resource "test_resource" "baz" { 192 woozles = "confuzles" 193 194 nested { 195 value = "42" 196 } 197 } 198 199 # test_resource.baz[0]: (deposed object 5678) 200 resource "test_resource" "baz" { 201 woozles = "confuzles" 202 203 nested { 204 value = "42" 205 } 206 }` 207 208 const stateWithMoreOutputsOutput = `# test_resource.baz[0]: 209 resource "test_resource" "baz" { 210 woozles = "confuzles" 211 } 212 213 214 Outputs: 215 216 bool_var = true 217 int_var = 42 218 map_var = { 219 "first" = "foo" 220 "second" = "bar" 221 } 222 sensitive_var = (sensitive value) 223 string_var = "string value"` 224 225 func basicState(t *testing.T) *states.State { 226 state := states.NewState() 227 228 rootModule := state.RootModule() 229 if rootModule == nil { 230 t.Errorf("root module is nil; want valid object") 231 } 232 233 rootModule.SetLocalValue("foo", cty.StringVal("foo value")) 234 rootModule.SetOutputValue("bar", cty.StringVal("bar value"), false) 235 rootModule.SetResourceInstanceCurrent( 236 addrs.Resource{ 237 Mode: addrs.ManagedResourceMode, 238 Type: "test_resource", 239 Name: "baz", 240 }.Instance(addrs.IntKey(0)), 241 &states.ResourceInstanceObjectSrc{ 242 Status: states.ObjectReady, 243 SchemaVersion: 1, 244 AttrsJSON: []byte(`{"woozles":"confuzles"}`), 245 }, 246 addrs.AbsProviderConfig{ 247 Provider: addrs.NewDefaultProvider("test"), 248 Module: addrs.RootModule, 249 }, 250 ) 251 rootModule.SetResourceInstanceCurrent( 252 addrs.Resource{ 253 Mode: addrs.DataResourceMode, 254 Type: "test_data_source", 255 Name: "data", 256 }.Instance(addrs.NoKey), 257 &states.ResourceInstanceObjectSrc{ 258 Status: states.ObjectReady, 259 SchemaVersion: 1, 260 AttrsJSON: []byte(`{"compute":"sure"}`), 261 }, 262 addrs.AbsProviderConfig{ 263 Provider: addrs.NewDefaultProvider("test"), 264 Module: addrs.RootModule, 265 }, 266 ) 267 return state 268 } 269 270 func stateWithMoreOutputs(t *testing.T) *states.State { 271 state := states.NewState() 272 273 rootModule := state.RootModule() 274 if rootModule == nil { 275 t.Errorf("root module is nil; want valid object") 276 } 277 278 rootModule.SetOutputValue("string_var", cty.StringVal("string value"), false) 279 rootModule.SetOutputValue("int_var", cty.NumberIntVal(42), false) 280 rootModule.SetOutputValue("bool_var", cty.BoolVal(true), false) 281 rootModule.SetOutputValue("sensitive_var", cty.StringVal("secret!!!"), true) 282 rootModule.SetOutputValue("map_var", cty.MapVal(map[string]cty.Value{ 283 "first": cty.StringVal("foo"), 284 "second": cty.StringVal("bar"), 285 }), false) 286 287 rootModule.SetResourceInstanceCurrent( 288 addrs.Resource{ 289 Mode: addrs.ManagedResourceMode, 290 Type: "test_resource", 291 Name: "baz", 292 }.Instance(addrs.IntKey(0)), 293 &states.ResourceInstanceObjectSrc{ 294 Status: states.ObjectReady, 295 SchemaVersion: 1, 296 AttrsJSON: []byte(`{"woozles":"confuzles"}`), 297 }, 298 addrs.AbsProviderConfig{ 299 Provider: addrs.NewDefaultProvider("test"), 300 Module: addrs.RootModule, 301 }, 302 ) 303 return state 304 } 305 306 func nestedState(t *testing.T) *states.State { 307 state := states.NewState() 308 309 rootModule := state.RootModule() 310 if rootModule == nil { 311 t.Errorf("root module is nil; want valid object") 312 } 313 314 rootModule.SetResourceInstanceCurrent( 315 addrs.Resource{ 316 Mode: addrs.ManagedResourceMode, 317 Type: "test_resource", 318 Name: "baz", 319 }.Instance(addrs.IntKey(0)), 320 &states.ResourceInstanceObjectSrc{ 321 Status: states.ObjectReady, 322 SchemaVersion: 1, 323 AttrsJSON: []byte(`{"woozles":"confuzles","nested": [{"value": "42"}]}`), 324 }, 325 addrs.AbsProviderConfig{ 326 Provider: addrs.NewDefaultProvider("test"), 327 Module: addrs.RootModule, 328 }, 329 ) 330 return state 331 } 332 333 func deposedState(t *testing.T) *states.State { 334 state := nestedState(t) 335 rootModule := state.RootModule() 336 rootModule.SetResourceInstanceDeposed( 337 addrs.Resource{ 338 Mode: addrs.ManagedResourceMode, 339 Type: "test_resource", 340 Name: "baz", 341 }.Instance(addrs.IntKey(0)), 342 states.DeposedKey("1234"), 343 &states.ResourceInstanceObjectSrc{ 344 Status: states.ObjectReady, 345 SchemaVersion: 1, 346 AttrsJSON: []byte(`{"woozles":"confuzles","nested": [{"value": "42"}]}`), 347 }, 348 addrs.AbsProviderConfig{ 349 Provider: addrs.NewDefaultProvider("test"), 350 Module: addrs.RootModule, 351 }, 352 ) 353 return state 354 } 355 356 // replicate a corrupt resource where only a deposed exists 357 func onlyDeposedState(t *testing.T) *states.State { 358 state := states.NewState() 359 360 rootModule := state.RootModule() 361 if rootModule == nil { 362 t.Errorf("root module is nil; want valid object") 363 } 364 365 rootModule.SetResourceInstanceDeposed( 366 addrs.Resource{ 367 Mode: addrs.ManagedResourceMode, 368 Type: "test_resource", 369 Name: "baz", 370 }.Instance(addrs.IntKey(0)), 371 states.DeposedKey("1234"), 372 &states.ResourceInstanceObjectSrc{ 373 Status: states.ObjectReady, 374 SchemaVersion: 1, 375 AttrsJSON: []byte(`{"woozles":"confuzles","nested": [{"value": "42"}]}`), 376 }, 377 addrs.AbsProviderConfig{ 378 Provider: addrs.NewDefaultProvider("test"), 379 Module: addrs.RootModule, 380 }, 381 ) 382 rootModule.SetResourceInstanceDeposed( 383 addrs.Resource{ 384 Mode: addrs.ManagedResourceMode, 385 Type: "test_resource", 386 Name: "baz", 387 }.Instance(addrs.IntKey(0)), 388 states.DeposedKey("5678"), 389 &states.ResourceInstanceObjectSrc{ 390 Status: states.ObjectReady, 391 SchemaVersion: 1, 392 AttrsJSON: []byte(`{"woozles":"confuzles","nested": [{"value": "42"}]}`), 393 }, 394 addrs.AbsProviderConfig{ 395 Provider: addrs.NewDefaultProvider("test"), 396 Module: addrs.RootModule, 397 }, 398 ) 399 return state 400 }