kubeform.dev/terraform-backend-sdk@v0.0.0-20220310143633-45f07fe731c5/configs/module_test.go (about) 1 package configs 2 3 import ( 4 "strings" 5 "testing" 6 7 "kubeform.dev/terraform-backend-sdk/addrs" 8 ) 9 10 // TestNewModule_provider_fqns exercises module.gatherProviderLocalNames() 11 func TestNewModule_provider_local_name(t *testing.T) { 12 mod, diags := testModuleFromDir("testdata/providers-explicit-fqn") 13 if diags.HasErrors() { 14 t.Fatal(diags.Error()) 15 } 16 17 p := addrs.NewProvider(addrs.DefaultProviderRegistryHost, "foo", "test") 18 if name, exists := mod.ProviderLocalNames[p]; !exists { 19 t.Fatal("provider FQN foo/test not found") 20 } else { 21 if name != "foo-test" { 22 t.Fatalf("provider localname mismatch: got %s, want foo-test", name) 23 } 24 } 25 26 // ensure the reverse lookup (fqn to local name) works as well 27 localName := mod.LocalNameForProvider(p) 28 if localName != "foo-test" { 29 t.Fatal("provider local name not found") 30 } 31 32 // if there is not a local name for a provider, it should return the type name 33 localName = mod.LocalNameForProvider(addrs.NewDefaultProvider("nonexist")) 34 if localName != "nonexist" { 35 t.Error("wrong local name returned for a non-local provider") 36 } 37 38 // can also look up the "terraform" provider and see that it sources is 39 // allowed to be overridden, even though there is a builtin provider 40 // called "terraform". 41 p = addrs.NewProvider(addrs.DefaultProviderRegistryHost, "not-builtin", "not-terraform") 42 if name, exists := mod.ProviderLocalNames[p]; !exists { 43 t.Fatal("provider FQN not-builtin/not-terraform not found") 44 } else { 45 if name != "terraform" { 46 t.Fatalf("provider localname mismatch: got %s, want terraform", name) 47 } 48 } 49 } 50 51 // This test validates the provider FQNs set in each Resource 52 func TestNewModule_resource_providers(t *testing.T) { 53 cfg, diags := testNestedModuleConfigFromDir(t, "testdata/valid-modules/nested-providers-fqns") 54 if diags.HasErrors() { 55 t.Fatal(diags.Error()) 56 } 57 58 // both the root and child module have two resources, one which should use 59 // the default implied provider and one explicitly using a provider set in 60 // required_providers 61 wantImplicit := addrs.NewDefaultProvider("test") 62 wantFoo := addrs.NewProvider(addrs.DefaultProviderRegistryHost, "foo", "test") 63 wantBar := addrs.NewProvider(addrs.DefaultProviderRegistryHost, "bar", "test") 64 65 // root module 66 if !cfg.Module.ManagedResources["test_instance.explicit"].Provider.Equals(wantFoo) { 67 t.Fatalf("wrong provider for \"test_instance.explicit\"\ngot: %s\nwant: %s", 68 cfg.Module.ManagedResources["test_instance.explicit"].Provider, 69 wantFoo, 70 ) 71 } 72 if !cfg.Module.ManagedResources["test_instance.implicit"].Provider.Equals(wantImplicit) { 73 t.Fatalf("wrong provider for \"test_instance.implicit\"\ngot: %s\nwant: %s", 74 cfg.Module.ManagedResources["test_instance.implicit"].Provider, 75 wantImplicit, 76 ) 77 } 78 79 // a data source 80 if !cfg.Module.DataResources["data.test_resource.explicit"].Provider.Equals(wantFoo) { 81 t.Fatalf("wrong provider for \"module.child.test_instance.explicit\"\ngot: %s\nwant: %s", 82 cfg.Module.ManagedResources["test_instance.explicit"].Provider, 83 wantBar, 84 ) 85 } 86 87 // child module 88 cm := cfg.Children["child"].Module 89 if !cm.ManagedResources["test_instance.explicit"].Provider.Equals(wantBar) { 90 t.Fatalf("wrong provider for \"module.child.test_instance.explicit\"\ngot: %s\nwant: %s", 91 cfg.Module.ManagedResources["test_instance.explicit"].Provider, 92 wantBar, 93 ) 94 } 95 if !cm.ManagedResources["test_instance.implicit"].Provider.Equals(wantImplicit) { 96 t.Fatalf("wrong provider for \"module.child.test_instance.implicit\"\ngot: %s\nwant: %s", 97 cfg.Module.ManagedResources["test_instance.implicit"].Provider, 98 wantImplicit, 99 ) 100 } 101 } 102 103 func TestProviderForLocalConfig(t *testing.T) { 104 mod, diags := testModuleFromDir("testdata/providers-explicit-fqn") 105 if diags.HasErrors() { 106 t.Fatal(diags.Error()) 107 } 108 lc := addrs.LocalProviderConfig{LocalName: "foo-test"} 109 got := mod.ProviderForLocalConfig(lc) 110 want := addrs.NewProvider(addrs.DefaultProviderRegistryHost, "foo", "test") 111 if !got.Equals(want) { 112 t.Fatalf("wrong result! got %#v, want %#v\n", got, want) 113 } 114 } 115 116 // At most one required_providers block per module is permitted. 117 func TestModule_required_providers_multiple(t *testing.T) { 118 _, diags := testModuleFromDir("testdata/invalid-modules/multiple-required-providers") 119 if !diags.HasErrors() { 120 t.Fatal("module should have error diags, but does not") 121 } 122 123 want := `Duplicate required providers configuration` 124 if got := diags.Error(); !strings.Contains(got, want) { 125 t.Fatalf("expected error to contain %q\nerror was:\n%s", want, got) 126 } 127 } 128 129 // A module may have required_providers configured in files loaded later than 130 // resources. These provider settings should still be reflected in the 131 // resources' configuration. 132 func TestModule_required_providers_after_resource(t *testing.T) { 133 mod, diags := testModuleFromDir("testdata/valid-modules/required-providers-after-resource") 134 if diags.HasErrors() { 135 t.Fatal(diags.Error()) 136 } 137 138 want := addrs.NewProvider(addrs.DefaultProviderRegistryHost, "foo", "test") 139 140 req, exists := mod.ProviderRequirements.RequiredProviders["test"] 141 if !exists { 142 t.Fatal("no provider requirements found for \"test\"") 143 } 144 if req.Type != want { 145 t.Errorf("wrong provider addr for \"test\"\ngot: %s\nwant: %s", 146 req.Type, want, 147 ) 148 } 149 150 if got := mod.ManagedResources["test_instance.my-instance"].Provider; !got.Equals(want) { 151 t.Errorf("wrong provider addr for \"test_instance.my-instance\"\ngot: %s\nwant: %s", 152 got, want, 153 ) 154 } 155 } 156 157 // We support overrides for required_providers blocks, which should replace the 158 // entire block for each provider localname, leaving other blocks unaffected. 159 // This should also be reflected in any resources in the module using this 160 // provider. 161 func TestModule_required_provider_overrides(t *testing.T) { 162 mod, diags := testModuleFromDir("testdata/valid-modules/required-providers-overrides") 163 if diags.HasErrors() { 164 t.Fatal(diags.Error()) 165 } 166 167 // The foo provider and resource should be unaffected 168 want := addrs.NewProvider(addrs.DefaultProviderRegistryHost, "acme", "foo") 169 req, exists := mod.ProviderRequirements.RequiredProviders["foo"] 170 if !exists { 171 t.Fatal("no provider requirements found for \"foo\"") 172 } 173 if req.Type != want { 174 t.Errorf("wrong provider addr for \"foo\"\ngot: %s\nwant: %s", 175 req.Type, want, 176 ) 177 } 178 if got := mod.ManagedResources["foo_thing.ft"].Provider; !got.Equals(want) { 179 t.Errorf("wrong provider addr for \"foo_thing.ft\"\ngot: %s\nwant: %s", 180 got, want, 181 ) 182 } 183 184 // The bar provider and resource should be using the override config 185 want = addrs.NewProvider(addrs.DefaultProviderRegistryHost, "blorp", "bar") 186 req, exists = mod.ProviderRequirements.RequiredProviders["bar"] 187 if !exists { 188 t.Fatal("no provider requirements found for \"bar\"") 189 } 190 if req.Type != want { 191 t.Errorf("wrong provider addr for \"bar\"\ngot: %s\nwant: %s", 192 req.Type, want, 193 ) 194 } 195 if gotVer, wantVer := req.Requirement.Required.String(), "~>2.0.0"; gotVer != wantVer { 196 t.Errorf("wrong provider version constraint for \"bar\"\ngot: %s\nwant: %s", 197 gotVer, wantVer, 198 ) 199 } 200 if got := mod.ManagedResources["bar_thing.bt"].Provider; !got.Equals(want) { 201 t.Errorf("wrong provider addr for \"bar_thing.bt\"\ngot: %s\nwant: %s", 202 got, want, 203 ) 204 } 205 } 206 207 // Resources without explicit provider configuration are assigned a provider 208 // implied based on the resource type. For example, this resource: 209 // 210 // resource foo_instance "test" { } 211 // 212 // is assigned a provider with type "foo". 213 // 214 // To find the correct provider, we first look in the module's provider 215 // requirements map for a local name matching the resource type, and fall back 216 // to a default provider if none is found. This applies to both managed and 217 // data resources. 218 func TestModule_implied_provider(t *testing.T) { 219 mod, diags := testModuleFromDir("testdata/valid-modules/implied-providers") 220 if diags.HasErrors() { 221 t.Fatal(diags.Error()) 222 } 223 224 // The three providers used in the config resources 225 foo := addrs.NewProvider("registry.acme.corp", "acme", "foo") 226 whatever := addrs.NewProvider(addrs.DefaultProviderRegistryHost, "acme", "something") 227 bar := addrs.NewDefaultProvider("bar") 228 229 // Verify that the registry.acme.corp/acme/foo provider is defined in the 230 // module provider requirements with local name "foo" 231 req, exists := mod.ProviderRequirements.RequiredProviders["foo"] 232 if !exists { 233 t.Fatal("no provider requirements found for \"foo\"") 234 } 235 if req.Type != foo { 236 t.Errorf("wrong provider addr for \"foo\"\ngot: %s\nwant: %s", 237 req.Type, foo, 238 ) 239 } 240 241 // Verify that the acme/something provider is defined in the 242 // module provider requirements with local name "whatever" 243 req, exists = mod.ProviderRequirements.RequiredProviders["whatever"] 244 if !exists { 245 t.Fatal("no provider requirements found for \"foo\"") 246 } 247 if req.Type != whatever { 248 t.Errorf("wrong provider addr for \"whatever\"\ngot: %s\nwant: %s", 249 req.Type, whatever, 250 ) 251 } 252 253 // Check that resources are assigned the correct providers: foo_* resources 254 // should have the custom foo provider, bar_* resources the default bar 255 // provider. 256 tests := []struct { 257 Address string 258 Provider addrs.Provider 259 }{ 260 {"foo_resource.a", foo}, 261 {"data.foo_resource.b", foo}, 262 {"bar_resource.c", bar}, 263 {"data.bar_resource.d", bar}, 264 {"whatever_resource.e", whatever}, 265 {"data.whatever_resource.f", whatever}, 266 } 267 for _, test := range tests { 268 resources := mod.ManagedResources 269 if strings.HasPrefix(test.Address, "data.") { 270 resources = mod.DataResources 271 } 272 resource, exists := resources[test.Address] 273 if !exists { 274 t.Errorf("could not find resource %q in %#v", test.Address, resources) 275 continue 276 } 277 if got := resource.Provider; !got.Equals(test.Provider) { 278 t.Errorf("wrong provider addr for %q\ngot: %s\nwant: %s", 279 test.Address, got, test.Provider, 280 ) 281 } 282 } 283 } 284 285 func TestImpliedProviderForUnqualifiedType(t *testing.T) { 286 mod, diags := testModuleFromDir("testdata/valid-modules/implied-providers") 287 if diags.HasErrors() { 288 t.Fatal(diags.Error()) 289 } 290 291 foo := addrs.NewProvider("registry.acme.corp", "acme", "foo") 292 whatever := addrs.NewProvider(addrs.DefaultProviderRegistryHost, "acme", "something") 293 bar := addrs.NewDefaultProvider("bar") 294 tf := addrs.NewBuiltInProvider("terraform") 295 296 tests := []struct { 297 Type string 298 Provider addrs.Provider 299 }{ 300 {"foo", foo}, 301 {"whatever", whatever}, 302 {"bar", bar}, 303 {"terraform", tf}, 304 } 305 for _, test := range tests { 306 got := mod.ImpliedProviderForUnqualifiedType(test.Type) 307 if !got.Equals(test.Provider) { 308 t.Errorf("wrong result for %q: got %#v, want %#v\n", test.Type, got, test.Provider) 309 } 310 } 311 }