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  ```