github.com/muratcelep/terraform@v1.1.0-beta2-not-internal-4/not-internal/terraform/transform_provider_test.go (about) 1 package terraform 2 3 import ( 4 "fmt" 5 "strings" 6 "testing" 7 8 "github.com/muratcelep/terraform/not-internal/addrs" 9 "github.com/muratcelep/terraform/not-internal/configs" 10 "github.com/muratcelep/terraform/not-internal/dag" 11 ) 12 13 func testProviderTransformerGraph(t *testing.T, cfg *configs.Config) *Graph { 14 t.Helper() 15 16 g := &Graph{Path: addrs.RootModuleInstance} 17 ct := &ConfigTransformer{Config: cfg} 18 if err := ct.Transform(g); err != nil { 19 t.Fatal(err) 20 } 21 arct := &AttachResourceConfigTransformer{Config: cfg} 22 if err := arct.Transform(g); err != nil { 23 t.Fatal(err) 24 } 25 26 return g 27 } 28 29 func TestProviderTransformer(t *testing.T) { 30 mod := testModule(t, "transform-provider-basic") 31 32 g := testProviderTransformerGraph(t, mod) 33 { 34 transform := &MissingProviderTransformer{} 35 if err := transform.Transform(g); err != nil { 36 t.Fatalf("err: %s", err) 37 } 38 } 39 40 transform := &ProviderTransformer{} 41 if err := transform.Transform(g); err != nil { 42 t.Fatalf("err: %s", err) 43 } 44 45 actual := strings.TrimSpace(g.String()) 46 expected := strings.TrimSpace(testTransformProviderBasicStr) 47 if actual != expected { 48 t.Fatalf("bad:\n\n%s", actual) 49 } 50 } 51 52 func TestProviderTransformer_ImportModuleChild(t *testing.T) { 53 mod := testModule(t, "import-module") 54 55 g := testProviderTransformerGraph(t, mod) 56 57 { 58 tf := &ImportStateTransformer{ 59 Config: mod, 60 Targets: []*ImportTarget{ 61 &ImportTarget{ 62 Addr: addrs.RootModuleInstance. 63 Child("child", addrs.NoKey). 64 ResourceInstance( 65 addrs.ManagedResourceMode, 66 "aws_instance", 67 "foo", 68 addrs.NoKey, 69 ), 70 ID: "bar", 71 }, 72 }, 73 } 74 75 if err := tf.Transform(g); err != nil { 76 t.Fatalf("err: %s", err) 77 } 78 t.Logf("graph after ImportStateTransformer:\n%s", g.String()) 79 } 80 81 { 82 tf := &MissingProviderTransformer{} 83 if err := tf.Transform(g); err != nil { 84 t.Fatalf("err: %s", err) 85 } 86 t.Logf("graph after MissingProviderTransformer:\n%s", g.String()) 87 } 88 89 { 90 tf := &ProviderTransformer{} 91 if err := tf.Transform(g); err != nil { 92 t.Fatalf("err: %s", err) 93 } 94 t.Logf("graph after ProviderTransformer:\n%s", g.String()) 95 } 96 97 actual := strings.TrimSpace(g.String()) 98 expected := strings.TrimSpace(testTransformImportModuleChildStr) 99 if actual != expected { 100 t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected) 101 } 102 } 103 104 // Test providers with FQNs that do not match the typeName 105 func TestProviderTransformer_fqns(t *testing.T) { 106 for _, mod := range []string{"fqns", "fqns-module"} { 107 mod := testModule(t, fmt.Sprintf("transform-provider-%s", mod)) 108 109 g := testProviderTransformerGraph(t, mod) 110 { 111 transform := &MissingProviderTransformer{Config: mod} 112 if err := transform.Transform(g); err != nil { 113 t.Fatalf("err: %s", err) 114 } 115 } 116 117 transform := &ProviderTransformer{Config: mod} 118 if err := transform.Transform(g); err != nil { 119 t.Fatalf("err: %s", err) 120 } 121 122 actual := strings.TrimSpace(g.String()) 123 expected := strings.TrimSpace(testTransformProviderBasicStr) 124 if actual != expected { 125 t.Fatalf("bad:\n\n%s", actual) 126 } 127 } 128 } 129 130 func TestCloseProviderTransformer(t *testing.T) { 131 mod := testModule(t, "transform-provider-basic") 132 g := testProviderTransformerGraph(t, mod) 133 134 { 135 transform := &MissingProviderTransformer{} 136 if err := transform.Transform(g); err != nil { 137 t.Fatalf("err: %s", err) 138 } 139 } 140 141 { 142 transform := &ProviderTransformer{} 143 if err := transform.Transform(g); err != nil { 144 t.Fatalf("err: %s", err) 145 } 146 } 147 148 { 149 transform := &CloseProviderTransformer{} 150 if err := transform.Transform(g); err != nil { 151 t.Fatalf("err: %s", err) 152 } 153 } 154 155 actual := strings.TrimSpace(g.String()) 156 expected := strings.TrimSpace(testTransformCloseProviderBasicStr) 157 if actual != expected { 158 t.Fatalf("bad:\n\n%s", actual) 159 } 160 } 161 162 func TestCloseProviderTransformer_withTargets(t *testing.T) { 163 mod := testModule(t, "transform-provider-basic") 164 165 g := testProviderTransformerGraph(t, mod) 166 transforms := []GraphTransformer{ 167 &MissingProviderTransformer{}, 168 &ProviderTransformer{}, 169 &CloseProviderTransformer{}, 170 &TargetsTransformer{ 171 Targets: []addrs.Targetable{ 172 addrs.RootModuleInstance.Resource( 173 addrs.ManagedResourceMode, "something", "else", 174 ), 175 }, 176 }, 177 } 178 179 for _, tr := range transforms { 180 if err := tr.Transform(g); err != nil { 181 t.Fatalf("err: %s", err) 182 } 183 } 184 185 actual := strings.TrimSpace(g.String()) 186 expected := strings.TrimSpace(``) 187 if actual != expected { 188 t.Fatalf("expected:%s\n\ngot:\n\n%s", expected, actual) 189 } 190 } 191 192 func TestMissingProviderTransformer(t *testing.T) { 193 mod := testModule(t, "transform-provider-missing") 194 195 g := testProviderTransformerGraph(t, mod) 196 { 197 transform := &MissingProviderTransformer{} 198 if err := transform.Transform(g); err != nil { 199 t.Fatalf("err: %s", err) 200 } 201 } 202 203 { 204 transform := &ProviderTransformer{} 205 if err := transform.Transform(g); err != nil { 206 t.Fatalf("err: %s", err) 207 } 208 } 209 210 { 211 transform := &CloseProviderTransformer{} 212 if err := transform.Transform(g); err != nil { 213 t.Fatalf("err: %s", err) 214 } 215 } 216 217 actual := strings.TrimSpace(g.String()) 218 expected := strings.TrimSpace(testTransformMissingProviderBasicStr) 219 if actual != expected { 220 t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual) 221 } 222 } 223 224 func TestMissingProviderTransformer_grandchildMissing(t *testing.T) { 225 mod := testModule(t, "transform-provider-missing-grandchild") 226 227 concrete := func(a *NodeAbstractProvider) dag.Vertex { return a } 228 229 g := testProviderTransformerGraph(t, mod) 230 { 231 transform := transformProviders(concrete, mod) 232 if err := transform.Transform(g); err != nil { 233 t.Fatalf("err: %s", err) 234 } 235 } 236 { 237 transform := &TransitiveReductionTransformer{} 238 if err := transform.Transform(g); err != nil { 239 t.Fatalf("err: %s", err) 240 } 241 } 242 243 actual := strings.TrimSpace(g.String()) 244 expected := strings.TrimSpace(testTransformMissingGrandchildProviderStr) 245 if actual != expected { 246 t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual) 247 } 248 } 249 250 func TestPruneProviderTransformer(t *testing.T) { 251 mod := testModule(t, "transform-provider-prune") 252 253 g := testProviderTransformerGraph(t, mod) 254 { 255 transform := &MissingProviderTransformer{} 256 if err := transform.Transform(g); err != nil { 257 t.Fatalf("err: %s", err) 258 } 259 } 260 261 { 262 transform := &ProviderTransformer{} 263 if err := transform.Transform(g); err != nil { 264 t.Fatalf("err: %s", err) 265 } 266 } 267 268 { 269 transform := &CloseProviderTransformer{} 270 if err := transform.Transform(g); err != nil { 271 t.Fatalf("err: %s", err) 272 } 273 } 274 275 { 276 transform := &PruneProviderTransformer{} 277 if err := transform.Transform(g); err != nil { 278 t.Fatalf("err: %s", err) 279 } 280 } 281 282 actual := strings.TrimSpace(g.String()) 283 expected := strings.TrimSpace(testTransformPruneProviderBasicStr) 284 if actual != expected { 285 t.Fatalf("bad:\n\n%s", actual) 286 } 287 } 288 289 // the child module resource is attached to the configured parent provider 290 func TestProviderConfigTransformer_parentProviders(t *testing.T) { 291 mod := testModule(t, "transform-provider-inherit") 292 concrete := func(a *NodeAbstractProvider) dag.Vertex { return a } 293 294 g := testProviderTransformerGraph(t, mod) 295 { 296 tf := transformProviders(concrete, mod) 297 if err := tf.Transform(g); err != nil { 298 t.Fatalf("err: %s", err) 299 } 300 } 301 302 actual := strings.TrimSpace(g.String()) 303 expected := strings.TrimSpace(testTransformModuleProviderConfigStr) 304 if actual != expected { 305 t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual) 306 } 307 } 308 309 // the child module resource is attached to the configured grand-parent provider 310 func TestProviderConfigTransformer_grandparentProviders(t *testing.T) { 311 mod := testModule(t, "transform-provider-grandchild-inherit") 312 concrete := func(a *NodeAbstractProvider) dag.Vertex { return a } 313 314 g := testProviderTransformerGraph(t, mod) 315 { 316 tf := transformProviders(concrete, mod) 317 if err := tf.Transform(g); err != nil { 318 t.Fatalf("err: %s", err) 319 } 320 } 321 322 actual := strings.TrimSpace(g.String()) 323 expected := strings.TrimSpace(testTransformModuleProviderGrandparentStr) 324 if actual != expected { 325 t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual) 326 } 327 } 328 329 func TestProviderConfigTransformer_inheritOldSkool(t *testing.T) { 330 mod := testModuleInline(t, map[string]string{ 331 "main.tf": ` 332 provider "test" { 333 test_string = "config" 334 } 335 336 module "moda" { 337 source = "./moda" 338 } 339 `, 340 341 "moda/main.tf": ` 342 resource "test_object" "a" { 343 } 344 `, 345 }) 346 concrete := func(a *NodeAbstractProvider) dag.Vertex { return a } 347 348 g := testProviderTransformerGraph(t, mod) 349 { 350 tf := transformProviders(concrete, mod) 351 if err := tf.Transform(g); err != nil { 352 t.Fatalf("err: %s", err) 353 } 354 } 355 356 expected := `module.moda.test_object.a 357 provider["registry.terraform.io/hashicorp/test"] 358 provider["registry.terraform.io/hashicorp/test"]` 359 360 actual := strings.TrimSpace(g.String()) 361 if actual != expected { 362 t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual) 363 } 364 } 365 366 // Verify that configurations which are not recommended yet supported still work 367 func TestProviderConfigTransformer_nestedModuleProviders(t *testing.T) { 368 mod := testModuleInline(t, map[string]string{ 369 "main.tf": ` 370 terraform { 371 required_providers { 372 test = { 373 source = "registry.terraform.io/hashicorp/test" 374 } 375 } 376 } 377 378 provider "test" { 379 alias = "z" 380 test_string = "config" 381 } 382 383 module "moda" { 384 source = "./moda" 385 providers = { 386 test.x = test.z 387 } 388 } 389 `, 390 391 "moda/main.tf": ` 392 terraform { 393 required_providers { 394 test = { 395 source = "registry.terraform.io/hashicorp/test" 396 configuration_aliases = [ test.x ] 397 } 398 } 399 } 400 401 provider "test" { 402 test_string = "config" 403 } 404 405 // this should connect to this module's provider 406 resource "test_object" "a" { 407 } 408 409 resource "test_object" "x" { 410 provider = test.x 411 } 412 413 module "modb" { 414 source = "./modb" 415 } 416 `, 417 418 "moda/modb/main.tf": ` 419 # this should end up with the provider from the parent module 420 resource "test_object" "a" { 421 } 422 `, 423 }) 424 concrete := func(a *NodeAbstractProvider) dag.Vertex { return a } 425 426 g := testProviderTransformerGraph(t, mod) 427 { 428 tf := transformProviders(concrete, mod) 429 if err := tf.Transform(g); err != nil { 430 t.Fatalf("err: %s", err) 431 } 432 } 433 434 expected := `module.moda.module.modb.test_object.a 435 module.moda.provider["registry.terraform.io/hashicorp/test"] 436 module.moda.provider["registry.terraform.io/hashicorp/test"] 437 module.moda.test_object.a 438 module.moda.provider["registry.terraform.io/hashicorp/test"] 439 module.moda.test_object.x 440 provider["registry.terraform.io/hashicorp/test"].z 441 provider["registry.terraform.io/hashicorp/test"].z` 442 443 actual := strings.TrimSpace(g.String()) 444 if actual != expected { 445 t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual) 446 } 447 } 448 449 const testTransformProviderBasicStr = ` 450 aws_instance.web 451 provider["registry.terraform.io/hashicorp/aws"] 452 provider["registry.terraform.io/hashicorp/aws"] 453 ` 454 455 const testTransformCloseProviderBasicStr = ` 456 aws_instance.web 457 provider["registry.terraform.io/hashicorp/aws"] 458 provider["registry.terraform.io/hashicorp/aws"] 459 provider["registry.terraform.io/hashicorp/aws"] (close) 460 aws_instance.web 461 provider["registry.terraform.io/hashicorp/aws"] 462 ` 463 464 const testTransformMissingProviderBasicStr = ` 465 aws_instance.web 466 provider["registry.terraform.io/hashicorp/aws"] 467 foo_instance.web 468 provider["registry.terraform.io/hashicorp/foo"] 469 provider["registry.terraform.io/hashicorp/aws"] 470 provider["registry.terraform.io/hashicorp/aws"] (close) 471 aws_instance.web 472 provider["registry.terraform.io/hashicorp/aws"] 473 provider["registry.terraform.io/hashicorp/foo"] 474 provider["registry.terraform.io/hashicorp/foo"] (close) 475 foo_instance.web 476 provider["registry.terraform.io/hashicorp/foo"] 477 ` 478 479 const testTransformMissingGrandchildProviderStr = ` 480 module.sub.module.subsub.bar_instance.two 481 provider["registry.terraform.io/hashicorp/bar"] 482 module.sub.module.subsub.foo_instance.one 483 module.sub.provider["registry.terraform.io/hashicorp/foo"] 484 module.sub.provider["registry.terraform.io/hashicorp/foo"] 485 provider["registry.terraform.io/hashicorp/bar"] 486 ` 487 488 const testTransformPruneProviderBasicStr = ` 489 foo_instance.web 490 provider["registry.terraform.io/hashicorp/foo"] 491 provider["registry.terraform.io/hashicorp/foo"] 492 provider["registry.terraform.io/hashicorp/foo"] (close) 493 foo_instance.web 494 provider["registry.terraform.io/hashicorp/foo"] 495 ` 496 497 const testTransformModuleProviderConfigStr = ` 498 module.child.aws_instance.thing 499 provider["registry.terraform.io/hashicorp/aws"].foo 500 provider["registry.terraform.io/hashicorp/aws"].foo 501 ` 502 503 const testTransformModuleProviderGrandparentStr = ` 504 module.child.module.grandchild.aws_instance.baz 505 provider["registry.terraform.io/hashicorp/aws"].foo 506 provider["registry.terraform.io/hashicorp/aws"].foo 507 ` 508 509 const testTransformImportModuleChildStr = ` 510 module.child.aws_instance.foo 511 provider["registry.terraform.io/hashicorp/aws"] 512 module.child.aws_instance.foo (import id "bar") 513 provider["registry.terraform.io/hashicorp/aws"] 514 module.child.module.nested.aws_instance.foo 515 provider["registry.terraform.io/hashicorp/aws"] 516 provider["registry.terraform.io/hashicorp/aws"]`