github.com/muratcelep/terraform@v1.1.0-beta2-not-internal-4/not-internal/configs/module_test.go (about) 1 package configs 2 3 import ( 4 "strings" 5 "testing" 6 7 "github.com/muratcelep/terraform/not-internal/addrs" 8 "github.com/zclconf/go-cty/cty" 9 ) 10 11 // TestNewModule_provider_fqns exercises module.gatherProviderLocalNames() 12 func TestNewModule_provider_local_name(t *testing.T) { 13 mod, diags := testModuleFromDir("testdata/providers-explicit-fqn") 14 if diags.HasErrors() { 15 t.Fatal(diags.Error()) 16 } 17 18 p := addrs.NewProvider(addrs.DefaultProviderRegistryHost, "foo", "test") 19 if name, exists := mod.ProviderLocalNames[p]; !exists { 20 t.Fatal("provider FQN foo/test not found") 21 } else { 22 if name != "foo-test" { 23 t.Fatalf("provider localname mismatch: got %s, want foo-test", name) 24 } 25 } 26 27 // ensure the reverse lookup (fqn to local name) works as well 28 localName := mod.LocalNameForProvider(p) 29 if localName != "foo-test" { 30 t.Fatal("provider local name not found") 31 } 32 33 // if there is not a local name for a provider, it should return the type name 34 localName = mod.LocalNameForProvider(addrs.NewDefaultProvider("nonexist")) 35 if localName != "nonexist" { 36 t.Error("wrong local name returned for a non-local provider") 37 } 38 39 // can also look up the "terraform" provider and see that it sources is 40 // allowed to be overridden, even though there is a builtin provider 41 // called "terraform". 42 p = addrs.NewProvider(addrs.DefaultProviderRegistryHost, "not-builtin", "not-terraform") 43 if name, exists := mod.ProviderLocalNames[p]; !exists { 44 t.Fatal("provider FQN not-builtin/not-terraform not found") 45 } else { 46 if name != "terraform" { 47 t.Fatalf("provider localname mismatch: got %s, want terraform", name) 48 } 49 } 50 } 51 52 // This test validates the provider FQNs set in each Resource 53 func TestNewModule_resource_providers(t *testing.T) { 54 cfg, diags := testNestedModuleConfigFromDir(t, "testdata/valid-modules/nested-providers-fqns") 55 if diags.HasErrors() { 56 t.Fatal(diags.Error()) 57 } 58 59 // both the root and child module have two resources, one which should use 60 // the default implied provider and one explicitly using a provider set in 61 // required_providers 62 wantImplicit := addrs.NewDefaultProvider("test") 63 wantFoo := addrs.NewProvider(addrs.DefaultProviderRegistryHost, "foo", "test") 64 wantBar := addrs.NewProvider(addrs.DefaultProviderRegistryHost, "bar", "test") 65 66 // root module 67 if !cfg.Module.ManagedResources["test_instance.explicit"].Provider.Equals(wantFoo) { 68 t.Fatalf("wrong provider for \"test_instance.explicit\"\ngot: %s\nwant: %s", 69 cfg.Module.ManagedResources["test_instance.explicit"].Provider, 70 wantFoo, 71 ) 72 } 73 if !cfg.Module.ManagedResources["test_instance.implicit"].Provider.Equals(wantImplicit) { 74 t.Fatalf("wrong provider for \"test_instance.implicit\"\ngot: %s\nwant: %s", 75 cfg.Module.ManagedResources["test_instance.implicit"].Provider, 76 wantImplicit, 77 ) 78 } 79 80 // a data source 81 if !cfg.Module.DataResources["data.test_resource.explicit"].Provider.Equals(wantFoo) { 82 t.Fatalf("wrong provider for \"module.child.test_instance.explicit\"\ngot: %s\nwant: %s", 83 cfg.Module.ManagedResources["test_instance.explicit"].Provider, 84 wantBar, 85 ) 86 } 87 88 // child module 89 cm := cfg.Children["child"].Module 90 if !cm.ManagedResources["test_instance.explicit"].Provider.Equals(wantBar) { 91 t.Fatalf("wrong provider for \"module.child.test_instance.explicit\"\ngot: %s\nwant: %s", 92 cfg.Module.ManagedResources["test_instance.explicit"].Provider, 93 wantBar, 94 ) 95 } 96 if !cm.ManagedResources["test_instance.implicit"].Provider.Equals(wantImplicit) { 97 t.Fatalf("wrong provider for \"module.child.test_instance.implicit\"\ngot: %s\nwant: %s", 98 cfg.Module.ManagedResources["test_instance.implicit"].Provider, 99 wantImplicit, 100 ) 101 } 102 } 103 104 func TestProviderForLocalConfig(t *testing.T) { 105 mod, diags := testModuleFromDir("testdata/providers-explicit-fqn") 106 if diags.HasErrors() { 107 t.Fatal(diags.Error()) 108 } 109 lc := addrs.LocalProviderConfig{LocalName: "foo-test"} 110 got := mod.ProviderForLocalConfig(lc) 111 want := addrs.NewProvider(addrs.DefaultProviderRegistryHost, "foo", "test") 112 if !got.Equals(want) { 113 t.Fatalf("wrong result! got %#v, want %#v\n", got, want) 114 } 115 } 116 117 // At most one required_providers block per module is permitted. 118 func TestModule_required_providers_multiple(t *testing.T) { 119 _, diags := testModuleFromDir("testdata/invalid-modules/multiple-required-providers") 120 if !diags.HasErrors() { 121 t.Fatal("module should have error diags, but does not") 122 } 123 124 want := `Duplicate required providers configuration` 125 if got := diags.Error(); !strings.Contains(got, want) { 126 t.Fatalf("expected error to contain %q\nerror was:\n%s", want, got) 127 } 128 } 129 130 // A module may have required_providers configured in files loaded later than 131 // resources. These provider settings should still be reflected in the 132 // resources' configuration. 133 func TestModule_required_providers_after_resource(t *testing.T) { 134 mod, diags := testModuleFromDir("testdata/valid-modules/required-providers-after-resource") 135 if diags.HasErrors() { 136 t.Fatal(diags.Error()) 137 } 138 139 want := addrs.NewProvider(addrs.DefaultProviderRegistryHost, "foo", "test") 140 141 req, exists := mod.ProviderRequirements.RequiredProviders["test"] 142 if !exists { 143 t.Fatal("no provider requirements found for \"test\"") 144 } 145 if req.Type != want { 146 t.Errorf("wrong provider addr for \"test\"\ngot: %s\nwant: %s", 147 req.Type, want, 148 ) 149 } 150 151 if got := mod.ManagedResources["test_instance.my-instance"].Provider; !got.Equals(want) { 152 t.Errorf("wrong provider addr for \"test_instance.my-instance\"\ngot: %s\nwant: %s", 153 got, want, 154 ) 155 } 156 } 157 158 // We support overrides for required_providers blocks, which should replace the 159 // entire block for each provider localname, leaving other blocks unaffected. 160 // This should also be reflected in any resources in the module using this 161 // provider. 162 func TestModule_required_provider_overrides(t *testing.T) { 163 mod, diags := testModuleFromDir("testdata/valid-modules/required-providers-overrides") 164 if diags.HasErrors() { 165 t.Fatal(diags.Error()) 166 } 167 168 // The foo provider and resource should be unaffected 169 want := addrs.NewProvider(addrs.DefaultProviderRegistryHost, "acme", "foo") 170 req, exists := mod.ProviderRequirements.RequiredProviders["foo"] 171 if !exists { 172 t.Fatal("no provider requirements found for \"foo\"") 173 } 174 if req.Type != want { 175 t.Errorf("wrong provider addr for \"foo\"\ngot: %s\nwant: %s", 176 req.Type, want, 177 ) 178 } 179 if got := mod.ManagedResources["foo_thing.ft"].Provider; !got.Equals(want) { 180 t.Errorf("wrong provider addr for \"foo_thing.ft\"\ngot: %s\nwant: %s", 181 got, want, 182 ) 183 } 184 185 // The bar provider and resource should be using the override config 186 want = addrs.NewProvider(addrs.DefaultProviderRegistryHost, "blorp", "bar") 187 req, exists = mod.ProviderRequirements.RequiredProviders["bar"] 188 if !exists { 189 t.Fatal("no provider requirements found for \"bar\"") 190 } 191 if req.Type != want { 192 t.Errorf("wrong provider addr for \"bar\"\ngot: %s\nwant: %s", 193 req.Type, want, 194 ) 195 } 196 if gotVer, wantVer := req.Requirement.Required.String(), "~>2.0.0"; gotVer != wantVer { 197 t.Errorf("wrong provider version constraint for \"bar\"\ngot: %s\nwant: %s", 198 gotVer, wantVer, 199 ) 200 } 201 if got := mod.ManagedResources["bar_thing.bt"].Provider; !got.Equals(want) { 202 t.Errorf("wrong provider addr for \"bar_thing.bt\"\ngot: %s\nwant: %s", 203 got, want, 204 ) 205 } 206 } 207 208 // Resources without explicit provider configuration are assigned a provider 209 // implied based on the resource type. For example, this resource: 210 // 211 // resource foo_instance "test" { } 212 // 213 // is assigned a provider with type "foo". 214 // 215 // To find the correct provider, we first look in the module's provider 216 // requirements map for a local name matching the resource type, and fall back 217 // to a default provider if none is found. This applies to both managed and 218 // data resources. 219 func TestModule_implied_provider(t *testing.T) { 220 mod, diags := testModuleFromDir("testdata/valid-modules/implied-providers") 221 if diags.HasErrors() { 222 t.Fatal(diags.Error()) 223 } 224 225 // The three providers used in the config resources 226 foo := addrs.NewProvider("registry.acme.corp", "acme", "foo") 227 whatever := addrs.NewProvider(addrs.DefaultProviderRegistryHost, "acme", "something") 228 bar := addrs.NewDefaultProvider("bar") 229 230 // Verify that the registry.acme.corp/acme/foo provider is defined in the 231 // module provider requirements with local name "foo" 232 req, exists := mod.ProviderRequirements.RequiredProviders["foo"] 233 if !exists { 234 t.Fatal("no provider requirements found for \"foo\"") 235 } 236 if req.Type != foo { 237 t.Errorf("wrong provider addr for \"foo\"\ngot: %s\nwant: %s", 238 req.Type, foo, 239 ) 240 } 241 242 // Verify that the acme/something provider is defined in the 243 // module provider requirements with local name "whatever" 244 req, exists = mod.ProviderRequirements.RequiredProviders["whatever"] 245 if !exists { 246 t.Fatal("no provider requirements found for \"foo\"") 247 } 248 if req.Type != whatever { 249 t.Errorf("wrong provider addr for \"whatever\"\ngot: %s\nwant: %s", 250 req.Type, whatever, 251 ) 252 } 253 254 // Check that resources are assigned the correct providers: foo_* resources 255 // should have the custom foo provider, bar_* resources the default bar 256 // provider. 257 tests := []struct { 258 Address string 259 Provider addrs.Provider 260 }{ 261 {"foo_resource.a", foo}, 262 {"data.foo_resource.b", foo}, 263 {"bar_resource.c", bar}, 264 {"data.bar_resource.d", bar}, 265 {"whatever_resource.e", whatever}, 266 {"data.whatever_resource.f", whatever}, 267 } 268 for _, test := range tests { 269 resources := mod.ManagedResources 270 if strings.HasPrefix(test.Address, "data.") { 271 resources = mod.DataResources 272 } 273 resource, exists := resources[test.Address] 274 if !exists { 275 t.Errorf("could not find resource %q in %#v", test.Address, resources) 276 continue 277 } 278 if got := resource.Provider; !got.Equals(test.Provider) { 279 t.Errorf("wrong provider addr for %q\ngot: %s\nwant: %s", 280 test.Address, got, test.Provider, 281 ) 282 } 283 } 284 } 285 286 func TestImpliedProviderForUnqualifiedType(t *testing.T) { 287 mod, diags := testModuleFromDir("testdata/valid-modules/implied-providers") 288 if diags.HasErrors() { 289 t.Fatal(diags.Error()) 290 } 291 292 foo := addrs.NewProvider("registry.acme.corp", "acme", "foo") 293 whatever := addrs.NewProvider(addrs.DefaultProviderRegistryHost, "acme", "something") 294 bar := addrs.NewDefaultProvider("bar") 295 tf := addrs.NewBuiltInProvider("terraform") 296 297 tests := []struct { 298 Type string 299 Provider addrs.Provider 300 }{ 301 {"foo", foo}, 302 {"whatever", whatever}, 303 {"bar", bar}, 304 {"terraform", tf}, 305 } 306 for _, test := range tests { 307 got := mod.ImpliedProviderForUnqualifiedType(test.Type) 308 if !got.Equals(test.Provider) { 309 t.Errorf("wrong result for %q: got %#v, want %#v\n", test.Type, got, test.Provider) 310 } 311 } 312 } 313 314 func TestModule_backend_override(t *testing.T) { 315 mod, diags := testModuleFromDir("testdata/valid-modules/override-backend") 316 if diags.HasErrors() { 317 t.Fatal(diags.Error()) 318 } 319 320 gotType := mod.Backend.Type 321 wantType := "bar" 322 323 if gotType != wantType { 324 t.Errorf("wrong result for backend type: got %#v, want %#v\n", gotType, wantType) 325 } 326 327 attrs, _ := mod.Backend.Config.JustAttributes() 328 329 gotAttr, diags := attrs["path"].Expr.Value(nil) 330 if diags.HasErrors() { 331 t.Fatal(diags.Error()) 332 } 333 334 wantAttr := cty.StringVal("CHANGED/relative/path/to/terraform.tfstate") 335 336 if !gotAttr.RawEquals(wantAttr) { 337 t.Errorf("wrong result for backend 'path': got %#v, want %#v\n", gotAttr, wantAttr) 338 } 339 } 340 341 // Unlike most other overrides, backend blocks do not require a base configuration in a primary 342 // configuration file, as an omitted backend there implies the local backend. 343 func TestModule_backend_override_no_base(t *testing.T) { 344 mod, diags := testModuleFromDir("testdata/valid-modules/override-backend-no-base") 345 if diags.HasErrors() { 346 t.Fatal(diags.Error()) 347 } 348 349 if mod.Backend == nil { 350 t.Errorf("expected module Backend not to be nil") 351 } 352 } 353 354 func TestModule_cloud_override_backend(t *testing.T) { 355 mod, diags := testModuleFromDir("testdata/valid-modules/override-backend-with-cloud") 356 if diags.HasErrors() { 357 t.Fatal(diags.Error()) 358 } 359 360 if mod.Backend != nil { 361 t.Errorf("expected module Backend to be nil") 362 } 363 364 if mod.CloudConfig == nil { 365 t.Errorf("expected module CloudConfig not to be nil") 366 } 367 } 368 369 // Unlike most other overrides, cloud blocks do not require a base configuration in a primary 370 // configuration file, as an omitted backend there implies the local backend and cloud blocks 371 // override backends. 372 func TestModule_cloud_override_no_base(t *testing.T) { 373 mod, diags := testModuleFromDir("testdata/valid-modules/override-cloud-no-base") 374 if diags.HasErrors() { 375 t.Fatal(diags.Error()) 376 } 377 378 if mod.CloudConfig == nil { 379 t.Errorf("expected module CloudConfig not to be nil") 380 } 381 } 382 383 func TestModule_cloud_override(t *testing.T) { 384 mod, diags := testModuleFromDir("testdata/valid-modules/override-cloud") 385 if diags.HasErrors() { 386 t.Fatal(diags.Error()) 387 } 388 389 attrs, _ := mod.CloudConfig.Config.JustAttributes() 390 391 gotAttr, diags := attrs["organization"].Expr.Value(nil) 392 if diags.HasErrors() { 393 t.Fatal(diags.Error()) 394 } 395 396 wantAttr := cty.StringVal("CHANGED") 397 398 if !gotAttr.RawEquals(wantAttr) { 399 t.Errorf("wrong result for Cloud 'organization': got %#v, want %#v\n", gotAttr, wantAttr) 400 } 401 402 // The override should have completely replaced the cloud block in the primary file, no merging 403 if attrs["should_not_be_present_with_override"] != nil { 404 t.Errorf("expected 'should_not_be_present_with_override' attribute to be nil") 405 } 406 } 407 408 func TestModule_cloud_duplicate_overrides(t *testing.T) { 409 _, diags := testModuleFromDir("testdata/invalid-modules/override-cloud-duplicates") 410 want := `Duplicate Terraform Cloud configurations` 411 if got := diags.Error(); !strings.Contains(got, want) { 412 t.Fatalf("expected module error to contain %q\nerror was:\n%s", want, got) 413 } 414 }