426 lines
17 KiB
Markdown
426 lines
17 KiB
Markdown
---
|
||
layout: "language"
|
||
page_title: "Provider Requirements - Configuration Language"
|
||
---
|
||
|
||
# Provider Requirements
|
||
|
||
Terraform relies on plugins called "providers" to interact with remote systems.
|
||
Terraform configurations must declare which providers they require, so that
|
||
Terraform can install and use them. This page documents how to declare providers
|
||
so Terraform can install them.
|
||
|
||
> **Hands-on:** Try the [Perform CRUD Operations with Providers](https://learn.hashicorp.com/tutorials/terraform/provider-use) tutorial on HashiCorp Learn.
|
||
|
||
Additionally, some providers require configuration (like endpoint URLs or cloud
|
||
regions) before they can be used. The [Provider
|
||
Configuration](/docs/language/providers/configuration.html) page documents how
|
||
to configure settings for providers.
|
||
|
||
-> **Note:** This page is about a feature of Terraform 0.13 and later; it also
|
||
describes how to use the more limited version of that feature that was available
|
||
in Terraform 0.12.
|
||
|
||
## Requiring Providers
|
||
|
||
Each Terraform module must declare which providers it requires, so that
|
||
Terraform can install and use them. Provider requirements are declared in a
|
||
`required_providers` block.
|
||
|
||
A provider requirement consists of a local name, a source location, and a
|
||
version constraint:
|
||
|
||
```hcl
|
||
terraform {
|
||
required_providers {
|
||
mycloud = {
|
||
source = "mycorp/mycloud"
|
||
version = "~> 1.0"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
The `required_providers` block must be nested inside the top-level
|
||
[`terraform` block](/docs/language/settings/index.html) (which can also contain other settings).
|
||
|
||
Each argument in the `required_providers` block enables one provider. The key
|
||
determines the provider's [local name](#local-names) (its unique identifier
|
||
within this module), and the value is an object with the following elements:
|
||
|
||
* `source` - the global [source address](#source-addresses) for the
|
||
provider you intend to use, such as `hashicorp/aws`.
|
||
|
||
* `version` - a [version constraint](#version-constraints) specifying
|
||
which subset of available provider versions the module is compatible with.
|
||
|
||
-> **Note:** The `name = { source, version }` syntax for `required_providers`
|
||
was added in Terraform v0.13. Previous versions of Terraform used a version
|
||
constraint string instead of an object (like `mycloud = "~> 1.0"`), and had no
|
||
way to specify provider source addresses. If you want to write a module that
|
||
works with both Terraform v0.12 and v0.13, see [v0.12-Compatible Provider
|
||
Requirements](#v0-12-compatible-provider-requirements) below.
|
||
|
||
## Names and Addresses
|
||
|
||
Each provider has two identifiers:
|
||
|
||
- A unique _source address,_ which is only used when requiring a provider.
|
||
- A _local name,_ which is used everywhere else in a Terraform module.
|
||
|
||
-> **Note:** Prior to Terraform 0.13, providers only had local names, since
|
||
Terraform could only automatically download providers distributed by HashiCorp.
|
||
|
||
### Local Names
|
||
|
||
Local names are module-specific, and are assigned when requiring a provider.
|
||
Local names must be unique per-module.
|
||
|
||
Outside of the `required_providers` block, Terraform configurations always refer
|
||
to providers by their local names. For example, the following configuration
|
||
declares `mycloud` as the local name for `mycorp/mycloud`, then uses that local
|
||
name when [configuring the provider](/docs/language/providers/configuration.html):
|
||
|
||
```hcl
|
||
terraform {
|
||
required_providers {
|
||
mycloud = {
|
||
source = "mycorp/mycloud"
|
||
version = "~> 1.0"
|
||
}
|
||
}
|
||
}
|
||
|
||
provider "mycloud" {
|
||
# ...
|
||
}
|
||
```
|
||
|
||
Users of a provider can choose any local name for it. However, nearly every
|
||
provider has a _preferred local name,_ which it uses as a prefix for all of its
|
||
resource types. (For example, resources from `hashicorp/aws` all begin with
|
||
`aws`, like `aws_instance` or `aws_security_group`.)
|
||
|
||
Whenever possible, you should use a provider's preferred local name. This makes
|
||
your configurations easier to understand, and lets you omit the `provider`
|
||
meta-argument from most of your resources. (If a resource doesn't specify which
|
||
provider configuration to use, Terraform interprets the first word of the
|
||
resource type as a local provider name.)
|
||
|
||
### Source Addresses
|
||
|
||
A provider's source address is its global identifier. It also specifies the
|
||
primary location where Terraform can download it.
|
||
|
||
Source addresses consist of three parts delimited by slashes (`/`), as
|
||
follows:
|
||
|
||
`[<HOSTNAME>/]<NAMESPACE>/<TYPE>`
|
||
|
||
* **Hostname** (optional): The hostname of the Terraform registry that
|
||
distributes the provider. If omitted, this defaults to
|
||
`registry.terraform.io`, the hostname of
|
||
[the public Terraform Registry](https://registry.terraform.io/).
|
||
|
||
* **Namespace:** An organizational namespace within the specified registry.
|
||
For the public Terraform Registry and for Terraform Cloud's private registry,
|
||
this represents the organization that publishes the provider. This field
|
||
may have other meanings for other registry hosts.
|
||
|
||
* **Type:** A short name for the platform or system the provider manages. Must
|
||
be unique within a particular namespace on a particular registry host.
|
||
|
||
The type is usually the provider's preferred local name. (There are
|
||
exceptions; for example,
|
||
[`hashicorp/google-beta`](https://registry.terraform.io/providers/hashicorp/google-beta/latest)
|
||
is an alternate release channel for `hashicorp/google`, so its preferred
|
||
local name is `google`. If in doubt, check the provider's documentation.)
|
||
|
||
For example,
|
||
[the official HTTP provider](https://registry.terraform.io/providers/hashicorp/http)
|
||
belongs to the `hashicorp` namespace on `registry.terraform.io`, so its
|
||
source address is `registry.terraform.io/hashicorp/http` or, more commonly, just
|
||
`hashicorp/http`.
|
||
|
||
The source address with all three components given explicitly is called the
|
||
provider's _fully-qualified address_. You will see fully-qualified address in
|
||
various outputs, like error messages, but in most cases a simplified display
|
||
version is used. This display version omits the source host when it is the
|
||
public registry, so you may see the shortened version `"hashicorp/random"` instead
|
||
of `"registry.terraform.io/hashicorp/random"`.
|
||
|
||
|
||
-> **Note:** If you omit the `source` argument when requiring a provider,
|
||
Terraform uses an implied source address of
|
||
`registry.terraform.io/hashicorp/<LOCAL NAME>`. This is a backward compatibility
|
||
feature to support the transition to Terraform 0.13; in modules that require
|
||
0.13 or later, we recommend using explicit source addresses for all providers.
|
||
|
||
### Handling Local Name Conflicts
|
||
|
||
Whenever possible, we recommend using a provider's preferred local name, which
|
||
is usually the same as the "type" portion of its source address.
|
||
|
||
However, it's sometimes necessary to use two providers with the same preferred
|
||
local name in the same module, usually when the providers are named after a
|
||
generic infrastructure type. Terraform requires unique local names for each
|
||
provider in a module, so you'll need to use a non-preferred name for at least
|
||
one of them.
|
||
|
||
When this happens, we recommend combining each provider's namespace with
|
||
its type name to produce compound local names with a dash:
|
||
|
||
```hcl
|
||
terraform {
|
||
required_providers {
|
||
# In the rare situation of using two providers that
|
||
# have the same type name -- "http" in this example --
|
||
# use a compound local name to distinguish them.
|
||
hashicorp-http = {
|
||
source = "hashicorp/http"
|
||
version = "~> 2.0"
|
||
}
|
||
mycorp-http = {
|
||
source = "mycorp/http"
|
||
version = "~> 1.0"
|
||
}
|
||
}
|
||
}
|
||
|
||
# References to these providers elsewhere in the
|
||
# module will use these compound local names.
|
||
provider "mycorp-http" {
|
||
# ...
|
||
}
|
||
|
||
data "http" "example" {
|
||
provider = hashicorp-http
|
||
#...
|
||
}
|
||
```
|
||
|
||
Terraform won't be able to guess either provider's name from its resource types,
|
||
so you'll need to specify a `provider` meta-argument for every affected
|
||
resource. However, readers and maintainers of your module will be able to easily
|
||
understand what's happening, and avoiding confusion is much more important than
|
||
avoiding typing.
|
||
|
||
## Version Constraints
|
||
|
||
Each provider plugin has its own set of available versions, allowing the
|
||
functionality of the provider to evolve over time. Each provider dependency you
|
||
declare should have a [version constraint](/docs/language/expressions/version-constraints.html) given in
|
||
the `version` argument so Terraform can select a single version per provider
|
||
that all modules are compatible with.
|
||
|
||
The `version` argument is optional; if omitted, Terraform will accept any
|
||
version of the provider as compatible. However, we strongly recommend specifying
|
||
a version constraint for every provider your module depends on.
|
||
|
||
To ensure Terraform always installs the same provider versions for a given
|
||
configuration, you can use Terraform CLI to create a
|
||
[dependency lock file](/docs/language/dependency-lock.html)
|
||
and commit it to version control along with your configuration. If a lock file
|
||
is present, Terraform Cloud, CLI, and Enterprise will all obey it when
|
||
installing providers.
|
||
|
||
> **Hands-on:** Try the [Lock and Upgrade Provider Versions](https://learn.hashicorp.com/tutorials/terraform/provider-versioning) tutorial on HashiCorp Learn.
|
||
|
||
### Best Practices for Provider Versions
|
||
|
||
Each module should at least declare the minimum provider version it is known
|
||
to work with, using the `>=` version constraint syntax:
|
||
|
||
```hcl
|
||
terraform {
|
||
required_providers {
|
||
mycloud = {
|
||
source = "hashicorp/aws"
|
||
version = ">= 1.0"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
A module intended to be used as the root of a configuration — that is, as the
|
||
directory where you'd run `terraform apply` — should also specify the
|
||
_maximum_ provider version it is intended to work with, to avoid accidental
|
||
upgrades to incompatible new versions. The `~>` operator is a convenient
|
||
shorthand for allowing only patch releases within a specific minor release:
|
||
|
||
```hcl
|
||
terraform {
|
||
required_providers {
|
||
mycloud = {
|
||
source = "hashicorp/aws"
|
||
version = "~> 1.0.4"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
Do not use `~>` (or other maximum-version constraints) for modules you intend to
|
||
reuse across many configurations, even if you know the module isn't compatible
|
||
with certain newer versions. Doing so can sometimes prevent errors, but more
|
||
often it forces users of the module to update many modules simultaneously when
|
||
performing routine upgrades. Specify a minimum version, document any known
|
||
incompatibilities, and let the root module manage the maximum version.
|
||
|
||
## Built-in Providers
|
||
|
||
While most Terraform providers are distributed separately as plugins, there
|
||
is currently one provider that is built in to Terraform itself, which
|
||
provides
|
||
[the `terraform_remote_state` data source](/docs/language/state/remote-state-data.html).
|
||
|
||
Because this provider is built in to Terraform, you don't need to declare it
|
||
in the `required_providers` block in order to use its features. However, for
|
||
consistency it _does_ have a special provider source address, which is
|
||
`terraform.io/builtin/terraform`. This address may sometimes appear in
|
||
Terraform's error messages and other output in order to unambiguously refer
|
||
to the built-in provider, as opposed to a hypothetical third-party provider
|
||
with the type name "terraform".
|
||
|
||
There is also an existing provider with the source address
|
||
`hashicorp/terraform`, which is an older version of the now-built-in provider
|
||
that was used by older versions of Terraform. `hashicorp/terraform` is not
|
||
compatible with Terraform v0.11 or later and should never be declared in a
|
||
`required_providers` block.
|
||
|
||
## In-house Providers
|
||
|
||
Anyone can develop and distribute their own Terraform providers. See
|
||
the [Call APIs with Terraform Providers](https://learn.hashicorp.com/collections/terraform/providers)
|
||
collection on HashiCorp Learn for more
|
||
about provider development.
|
||
|
||
Some organizations develop their own providers to configure
|
||
proprietary systems, and wish to use these providers from Terraform without
|
||
publishing them on the public Terraform Registry.
|
||
|
||
One option for distributing such a provider is to run an in-house _private_
|
||
registry, by implementing
|
||
[the provider registry protocol](/docs/internals/provider-registry-protocol.html).
|
||
|
||
Running an additional service just to distribute a single provider internally
|
||
may be undesirable, so Terraform also supports
|
||
[other provider installation methods](/docs/cli/config/config-file.html#provider-installation),
|
||
including placing provider plugins directly in specific directories in the
|
||
local filesystem, via _filesystem mirrors_.
|
||
|
||
All providers must have a [source address](#source-addresses) that includes
|
||
(or implies) the hostname of a registry, but that hostname does not need to
|
||
provide an actual registry service. For in-house providers that you intend to
|
||
distribute from a local filesystem directory, you can use an arbitrary hostname
|
||
in a domain your organization controls.
|
||
|
||
For example, if your corporate domain were `example.com` then you might choose
|
||
to use `terraform.example.com` as your placeholder hostname, even if that
|
||
hostname doesn't actually resolve in DNS. You can then choose any namespace and
|
||
type you wish to represent your in-house provider under that hostname, giving
|
||
a source address like `terraform.example.com/examplecorp/ourcloud`:
|
||
|
||
```hcl
|
||
terraform {
|
||
required_providers {
|
||
mycloud = {
|
||
source = "terraform.example.com/examplecorp/ourcloud"
|
||
version = ">= 1.0"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
To make version 1.0.0 of this provider available for installation from the
|
||
local filesystem, choose one of the
|
||
[implied local mirror directories](/docs/cli/config/config-file.html#implied-local-mirror-directories)
|
||
and create a directory structure under it like this:
|
||
|
||
```
|
||
terraform.example.com/examplecorp/ourcloud/1.0.0
|
||
```
|
||
|
||
Under that `1.0.0` directory, create one additional directory representing the
|
||
platform where you are running Terraform, such as `linux_amd64` for Linux on
|
||
an AMD64/x64 processor, and then place the provider plugin executable and any
|
||
other needed files in that directory.
|
||
|
||
Thus, on a Windows system, the provider plugin executable file might be at the
|
||
following path:
|
||
|
||
```
|
||
terraform.example.com/examplecorp/ourcloud/1.0.0/windows_amd64/terraform-provider-ourcloud.exe
|
||
```
|
||
|
||
If you later decide to switch to using a real private provider registry rather
|
||
than distribute binaries out of band, you can deploy the registry server at
|
||
`terraform.example.com` and retain the same namespace and type names, in which
|
||
case your existing modules will require no changes to locate the same provider
|
||
using your registry server.
|
||
|
||
## v0.12-Compatible Provider Requirements
|
||
|
||
Explicit provider source addresses were introduced with Terraform v0.13, so the
|
||
full provider requirements syntax is not supported by Terraform v0.12.
|
||
|
||
However, in order to allow writing modules that are compatible with both
|
||
Terraform v0.12 and v0.13, versions of Terraform between v0.12.26 and v0.13
|
||
will accept but ignore the `source` argument in a `required_providers` block.
|
||
|
||
Consider the following example written for Terraform v0.13:
|
||
|
||
```hcl
|
||
terraform {
|
||
required_providers {
|
||
aws = {
|
||
source = "hashicorp/aws"
|
||
version = "~> 1.0"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
Terraform v0.12.26 will accept syntax like the above but will understand it
|
||
in the same way as the following v0.12-style syntax:
|
||
|
||
```hcl
|
||
terraform {
|
||
required_providers {
|
||
aws = "~> 1.0"
|
||
}
|
||
}
|
||
```
|
||
|
||
In other words, Terraform v0.12.26 ignores the `source` argument and considers
|
||
only the `version` argument, using the given [local name](#local-names) as the
|
||
un-namespaced provider type to install.
|
||
|
||
When writing a module that is compatible with both Terraform v0.12.26 and
|
||
Terraform v0.13.0 or later, you must follow the following additional rules so
|
||
that both versions will select the same provider to install:
|
||
|
||
* Use only providers that can be automatically installed by Terraform v0.12.
|
||
Third-party providers, such as community providers in the Terraform Registry,
|
||
cannot be selected by Terraform v0.12 because it does not support the
|
||
hierarchical source address namespace.
|
||
|
||
* Ensure that your chosen local name exactly matches the "type" portion of the
|
||
source address given in the `source` argument, such as both being "aws" in
|
||
the examples above, because Terraform v0.12 will use the local name to
|
||
determine which provider plugin to download and install.
|
||
|
||
* If the provider belongs to the `hashicorp` namespace, as with the
|
||
`hashicorp/aws` provider shown above, omit the `source` argument and allow
|
||
Terraform v0.13 to select the `hashicorp` namespace by default.
|
||
|
||
* Provider type names must always be written in lowercase. Terraform v0.13
|
||
treats provider source addresses as case-insensitive, but Terraform v0.12
|
||
considers its legacy-style provider names to be case-sensitive. Using
|
||
lowercase will ensure that the name is selectable by both Terraform major
|
||
versions.
|
||
|
||
This compatibility mechanism is provided as a temporary transitional aid only.
|
||
When Terraform v0.12 detects a use of the new `source` argument it doesn't
|
||
understand, it will emit a warning to alert the user that it is disregarding
|
||
the source address given in that argument.
|