terraform/website/docs/configuration/provider-requirements.html.md

300 lines
12 KiB
Markdown
Raw Normal View History

---
layout: "docs"
page_title: "Provider Requirements - Configuration Language"
---
## Provider Requirements
-> **Note:** If you are using Terraform 0.11 or
earlier, see
[0.11 Configuration Language: Provider Versions](../configuration-0-11/providers.html#provider-versions) instead.
Terraform relies on plugins called "providers" to interact with remote systems.
Each provider offers a set of named
[resource types](resources.html#resource-types-and-arguments), and defines for
each resource type which arguments it accepts, which attributes it exports, and
how changes to resources of that type are actually applied to remote APIs.
You can discover publicly-available providers
[via the Terraform Registry](https://registry.terraform.io/browse/providers).
Which providers you will use will depend on which remote cloud services you are
intending to configure. Additionally, some Terraform providers provide
local-only functionality which is useful to integrate functionality offered by
different providers, such as generating random numbers to help construct
unique resource names.
Once you've selected one or more providers, use a `required_providers` block to
declare them so that Terraform will make them available for use. A provider
dependency consists of both 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 a
[`terraform` block](terraform.html). The `terraform` block can include other
settings too, but we'll only focus on `required_providers` here.
The keys inside the `required_providers` block represent each provider's
[local name](#local-names), which is the unique identifier for a provider within
a particular module. Each item inside the `required_providers` block is an
object expecting the following arguments:
* `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 `required_providers` object syntax described above was added in Terraform v0.13. Previous versions of Terraform used a single string instead of an object, with the string specifying only a version constraint. For example, `mycloud = "~> 1.0"`. Explicit provider source addresses are supported only in Terraform v0.13 and later.
### Source Addresses
A provider _source address_ both globally identifies a particular provider and
specifies the primary location from which Terraform can download it.
Source addresses consist of three parts delimited by slashes (`/`), as
follows:
* **Hostname**: the hostname of the Terraform registry that indexes the provider.
You can omit the hostname portion and its following slash if the provider
is hosted on [the public Terraform Registry](https://registry.terraform.io/),
whose hostname is `registry.terraform.io`.
* **Namespace**: an organizational namespace within the specified registry.
For the public Terraform Registry and Terraform Cloud's private registry,
this represents the organization that is publishing the provider. This field
may have other meanings for other registry hosts.
* **Type**: The provider type name, which must be unique within a particular
namespace on a particular registry host.
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 can be written as either `registry.terraform.io/hashicorp/http`
or, more commonly, just `hashicorp/http`.
-> **Note**: As a concession for backward compatibility with earlier versions of
Terraform, the `source` argument is actually optional. If you omit it, Terraform
will construct an implied source address by appending the local name to the prefix
`hashicorp/`. For example, a provider dependency with local name `http` that
does not have an explicit `source` will be treated as equivalent to
`hashicorp/http`. We recommend using explicit source addresses for all providers
in modules that require Terraform 0.13 or later, so a future reader of your
module can clearly see exactly which provider is required, without needing to
first understand this default behavior.
### Local Names
Full [source addresses](#source-addresses) are verbose, so the Terraform
language uses them only when declaring dependencies. We associate each required
provider with a module-specific _local name_, which is a short identifier that
will refer to the associated source address within declarations inside a
particular module.
```hcl
terraform {
required_providers {
mycloud = {
source = "mycorp/mycloud"
version = "~> 1.0"
}
}
}
```
The above example declares `mycloud` as the local name for `mycorp/mycloud`
(which is short for `registry.terraform.io/mycorp/mycloud`) in the current
module only. That means we will refer to this provider as `mycloud` elsewhere
in the module, such as in a `provider "mycloud"` block used to create a
[provider configuration](providers.html):
```hcl
provider "mycloud" {
# ...
}
```
We strongly recommend setting the local name of a provider to match the "type"
portion of its source address, as in the above example. Consistent use of the
provider's canonical type can help avoid the need for readers of the rest of
the module to refer to the `required_providers` block to understand which
provider the module is using.
The one situation where it is reasonable to use a different local name is the
relatively-rare case of having two providers in the same module that have the
same type name. In that case, Terraform requires choosing a unique local name
for each one. In that situation, we recommend to combine the namespace with
the type name to produce a compound local name to disambiguate:
```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" {
# ...
}
```
### Version Constraints
A [source address](#source-addresses) uniquely identifies a particular
provider, but each provider can have one or more distinct _versions_, allowing
the functionality of the provider to evolve over time. Each provider dependency
you declare should have a [version constraint](./version-constraints.html)
given in the `version` argument.
Each module should at least declare the minimum provider version it is known
to work with, using the `>=` version constraint syntax:
```
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
upgrading when new versions are released. The `~>` operator is a convenient
shorthand for allowing only patch releases within a specific minor release:
```
terraform {
required_providers {
mycloud = {
source = "hashicorp/aws"
version = "~> 1.0.4"
}
}
}
```
_Do not_ use the `~>` or other maximum-version constraints for modules you
intend to reuse across many configurations. All of the version constraints
across all modules in a configuration must work collectively to select a
single version to use, so many modules all specifying maximum version
constraints would require those upper limits to all be updated simultaneously
if one module begins requiring a newer provider version.
The `version` argument is optional. If you omit it, Terraform will accept
_any_ version of the provider as compatible. That's risky for a provider
distributed by a third-party, because they may release a version containing
breaking changes at any time and prevent you from making progress until you
update your configuration. We strongly recommend always specifying a version
constraint, as described above, for every provider your module depends on.
### 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/providers/terraform/d/remote_state.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
Some organizations develop their own providers to allow interacting with
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 though, so Terraform also supports
[other provider installation methods](https://github.com/hashicorp/terraform/blob/master/website/docs/commands/cli-config.html.markdown#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 host registry, but for an in-house provider that
you intend only to distribute from a local filesystem directory you can choose
an artificial hostname in a domain your organization controls and use that to
mark your in-house providers.
For example, if your corporate domain were `example.com` then you might choose
to use `terraform.example.com` as your artificial 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/commands/cli-config.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.
The provider plugin executable file might therefore be at the following path,
on a Windows system for the sake of example:
```
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 an artifical local hostname, 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 instead.