github.com/muratcelep/terraform@v1.1.0-beta2-not-internal-4/website/docs/language/modules/develop/providers.html.md (about) 1 --- 2 layout: "language" 3 page_title: "Providers Within Modules - Configuration Language" 4 --- 5 6 # Providers Within Modules 7 8 [inpage-providers]: #providers-within-modules 9 10 In a configuration with multiple modules, there are some special considerations 11 for how resources are associated with provider configurations. 12 13 Each resource in the configuration must be associated with one provider 14 configuration. Provider configurations, unlike most other concepts in 15 Terraform, are global to an entire Terraform configuration and can be shared 16 across module boundaries. Provider configurations can be defined only in a 17 root Terraform module. 18 19 Providers can be passed down to descendent modules in two ways: either 20 _implicitly_ through inheritance, or _explicitly_ via the `providers` argument 21 within a `module` block. These two options are discussed in more detail in the 22 following sections. 23 24 A module intended to be called by one or more other modules must not contain 25 any `provider` blocks. A module containing its own provider configurations is 26 not compatible with the `for_each`, `count`, and `depends_on` arguments that 27 were introduced in Terraform v0.13. For more information, see 28 [Legacy Shared Modules with Provider Configurations](#legacy-shared-modules-with-provider-configurations). 29 30 Provider configurations are used for all operations on associated resources, 31 including destroying remote objects and refreshing state. Terraform retains, as 32 part of its state, a reference to the provider configuration that was most 33 recently used to apply changes to each resource. When a `resource` block is 34 removed from the configuration, this record in the state will be used to locate 35 the appropriate configuration because the resource's `provider` argument 36 (if any) will no longer be present in the configuration. 37 38 As a consequence, you must ensure that all resources that belong to a 39 particular provider configuration are destroyed before you can remove that 40 provider configuration's block from your configuration. If Terraform finds 41 a resource instance tracked in the state whose provider configuration block is 42 no longer available then it will return an error during planning, prompting you 43 to reintroduce the provider configuration. 44 45 ## Provider Version Constraints in Modules 46 47 Although provider _configurations_ are shared between modules, each module must 48 declare its own [provider requirements](/docs/language/providers/requirements.html), so that 49 Terraform can ensure that there is a single version of the provider that is 50 compatible with all modules in the configuration and to specify the 51 [source address](/docs/language/providers/requirements.html#source-addresses) that serves as 52 the global (module-agnostic) identifier for a provider. 53 54 To declare that a module requires particular versions of a specific provider, 55 use a `required_providers` block inside a `terraform` block: 56 57 ```hcl 58 terraform { 59 required_providers { 60 aws = { 61 source = "hashicorp/aws" 62 version = ">= 2.7.0" 63 } 64 } 65 } 66 ``` 67 68 A provider requirement says, for example, "This module requires version v2.7.0 69 of the provider `hashicorp/aws` and will refer to it as `aws`." It doesn't, 70 however, specify any of the configuration settings that determine what remote 71 endpoints the provider will access, such as an AWS region; configuration 72 settings come from provider _configurations_, and a particular overall Terraform 73 configuration can potentially have 74 [several different configurations for the same provider](/docs/language/providers/configuration.html#alias-multiple-provider-configurations). 75 76 ## Provider Aliases Within Modules 77 78 To declare multiple configuration names for a provider within a module, add the 79 `configuration_aliases` argument: 80 81 ```hcl 82 terraform { 83 required_providers { 84 aws = { 85 source = "hashicorp/aws" 86 version = ">= 2.7.0" 87 configuration_aliases = [ aws.alternate ] 88 } 89 } 90 } 91 ``` 92 93 The above requirements are identical to the previous, with the addition of the 94 alias provider configuration name `aws.alternate`, which can be referenced by 95 resources using the `provider` argument. 96 97 If you are writing a shared Terraform module, constrain only the minimum 98 required provider version using a `>=` constraint. This should specify the 99 minimum version containing the features your module relies on, and thus allow a 100 user of your module to potentially select a newer provider version if other 101 features are needed by other parts of their overall configuration. 102 103 ## Implicit Provider Inheritance 104 105 For convenience in simple configurations, a child module automatically inherits 106 default (un-aliased) provider configurations from its parent. This means that 107 explicit `provider` blocks appear only in the root module, and downstream 108 modules can simply declare resources for that provider and have them 109 automatically associated with the root provider configurations. 110 111 For example, the root module might contain only a `provider` block and a 112 `module` block to instantiate a child module: 113 114 ```hcl 115 provider "aws" { 116 region = "us-west-1" 117 } 118 119 module "child" { 120 source = "./child" 121 } 122 ``` 123 124 The child module can then use any resource from this provider with no further 125 provider configuration required: 126 127 ```hcl 128 resource "aws_s3_bucket" "example" { 129 bucket = "provider-inherit-example" 130 } 131 ``` 132 133 We recommend using this approach when a single configuration for each provider 134 is sufficient for an entire configuration. 135 136 ~> **Note:** Only provider configurations are inherited by child modules, not provider source or version requirements. Each module must [declare its own provider requirements](/docs/language/providers/requirements.html). This is especially important for non-HashiCorp providers. 137 138 In more complex situations there may be 139 [multiple provider configurations](/docs/language/providers/configuration.html#alias-multiple-provider-configurations), 140 or a child module may need to use different provider settings than 141 its parent. For such situations, you must pass providers explicitly. 142 143 ## Passing Providers Explicitly 144 145 When child modules each need a different configuration of a particular 146 provider, or where the child module requires a different provider configuration 147 than its parent, you can use the `providers` argument within a `module` block 148 to explicitly define which provider configurations are available to the 149 child module. For example: 150 151 ```hcl 152 # The default "aws" configuration is used for AWS resources in the root 153 # module where no explicit provider instance is selected. 154 provider "aws" { 155 region = "us-west-1" 156 } 157 158 # An alternate configuration is also defined for a different 159 # region, using the alias "usw2". 160 provider "aws" { 161 alias = "usw2" 162 region = "us-west-2" 163 } 164 165 # An example child module is instantiated with the alternate configuration, 166 # so any AWS resources it defines will use the us-west-2 region. 167 module "example" { 168 source = "./example" 169 providers = { 170 aws = aws.usw2 171 } 172 } 173 ``` 174 175 The `providers` argument within a `module` block is similar to 176 [the `provider` argument](/docs/language/meta-arguments/resource-provider.html) 177 within a resource, but is a map rather than a single string because a module may 178 contain resources from many different providers. 179 180 The keys of the `providers` map are provider configuration names as expected by 181 the child module, and the values are the names of corresponding configurations 182 in the _current_ module. 183 184 Once the `providers` argument is used in a `module` block, it overrides all of 185 the default inheritance behavior, so it is necessary to enumerate mappings 186 for _all_ of the required providers. This is to avoid confusion and surprises 187 that may result when mixing both implicit and explicit provider passing. 188 189 Additional provider configurations (those with the `alias` argument set) are 190 _never_ inherited automatically by child modules, and so must always be passed 191 explicitly using the `providers` map. For example, a module 192 that configures connectivity between networks in two AWS regions is likely 193 to need both a source and a destination region. In that case, the root module 194 may look something like this: 195 196 ```hcl 197 provider "aws" { 198 alias = "usw1" 199 region = "us-west-1" 200 } 201 202 provider "aws" { 203 alias = "usw2" 204 region = "us-west-2" 205 } 206 207 module "tunnel" { 208 source = "./tunnel" 209 providers = { 210 aws.src = aws.usw1 211 aws.dst = aws.usw2 212 } 213 } 214 ``` 215 216 The subdirectory `./tunnel` must then declare the configuration aliases for the 217 provider so the calling module can pass configurations with these names in its `providers` argument: 218 219 ```hcl 220 terraform { 221 required_providers { 222 aws = { 223 source = "hashicorp/aws" 224 version = ">= 2.7.0" 225 configuration_aliases = [ aws.src, aws.dest ] 226 } 227 } 228 } 229 ``` 230 231 Each resource should then have its own `provider` attribute set to either 232 `aws.src` or `aws.dst` to choose which of the two provider configurations to 233 use. 234 235 ## Legacy Shared Modules with Provider Configurations 236 237 In Terraform v0.10 and earlier there was no explicit way to use different 238 configurations of a provider in different modules in the same configuration, 239 and so module authors commonly worked around this by writing `provider` blocks 240 directly inside their modules, making the module have its own separate 241 provider configurations separate from those declared in the root module. 242 243 However, that pattern had a significant drawback: because a provider 244 configuration is required to destroy the remote object associated with a 245 resource instance as well as to create or update it, a provider configuration 246 must always stay present in the overall Terraform configuration for longer 247 than all of the resources it manages. If a particular module includes 248 both resources and the provider configurations for those resources then 249 removing the module from its caller would violate that constraint: both the 250 resources and their associated providers would, in effect, be removed 251 simultaneously. 252 253 Terraform v0.11 introduced the mechanisms described in earlier sections to 254 allow passing provider configurations between modules in a structured way, and 255 thus we explicitly recommended against writing a child module with its own 256 provider configuration blocks. However, that legacy pattern continued to work 257 for compatibility purposes -- though with the same drawback -- until Terraform 258 v0.13. 259 260 Terraform v0.13 introduced the possibility for a module itself to use the 261 `for_each`, `count`, and `depends_on` arguments, but the implementation of 262 those unfortunately conflicted with the support for the legacy pattern. 263 264 To retain the backward compatibility as much as possible, Terraform v0.13 265 continues to support the legacy pattern for module blocks that do not use these 266 new features, but a module with its own provider configurations is not 267 compatible with `for_each`, `count`, or `depends_on`. Terraform will produce an 268 error if you attempt to combine these features. For example: 269 270 ``` 271 Error: Module does not support count 272 273 on main.tf line 15, in module "child": 274 15: count = 2 275 276 Module "child" cannot be used with count because it contains a nested provider 277 configuration for "aws", at child/main.tf:2,10-15. 278 279 This module can be made compatible with count by changing it to receive all of 280 its provider configurations from the calling module, by using the "providers" 281 argument in the calling module block. 282 ``` 283 284 To make a module compatible with the new features, you must remove all of the 285 `provider` blocks from its definition. 286 287 If the new version of the module declares `configuration_aliases`, or if the 288 calling module needs the child module to use different provider configurations 289 than its own default provider configurations, the calling module must then 290 include an explicit `providers` argument to describe which provider 291 configurations the child module will use: 292 293 ```hcl 294 provider "aws" { 295 region = "us-west-1" 296 } 297 298 provider "aws" { 299 region = "us-east-1" 300 alias = "east" 301 } 302 303 module "child" { 304 count = 2 305 providers = { 306 # By default, the child module would use the 307 # default (unaliased) AWS provider configuration 308 # using us-west-1, but this will override it 309 # to use the additional "east" configuration 310 # for its resources instead. 311 aws = aws.east 312 } 313 } 314 ``` 315 316 Since the association between resources and provider configurations is 317 static, module calls using `for_each` or `count` cannot pass different 318 provider configurations to different instances. If you need different 319 instances of your module to use different provider configurations then you 320 must use a separate `module` block for each distinct set of provider 321 configurations: 322 323 ```hcl 324 provider "aws" { 325 alias = "usw1" 326 region = "us-west-1" 327 } 328 329 provider "aws" { 330 alias = "usw2" 331 region = "us-west-2" 332 } 333 334 provider "google" { 335 alias = "usw1" 336 credentials = "${file("account.json")}" 337 project = "my-project-id" 338 region = "us-west1" 339 zone = "us-west1-a" 340 } 341 342 provider "google" { 343 alias = "usw2" 344 credentials = "${file("account.json")}" 345 project = "my-project-id" 346 region = "us-west2" 347 zone = "us-west2-a" 348 } 349 350 module "bucket_w1" { 351 source = "./publish_bucket" 352 providers = { 353 aws.src = aws.usw1 354 google.src = google.usw2 355 } 356 } 357 358 module "bucket_w2" { 359 source = "./publish_bucket" 360 providers = { 361 aws.src = aws.usw2 362 google.src = google.usw2 363 } 364 } 365 ```