From b1eb9dcfcf5b3be5e544c1ccda6f667e2b16a527 Mon Sep 17 00:00:00 2001 From: Nick Fagerlund Date: Mon, 23 Mar 2020 14:00:11 -0400 Subject: [PATCH] website: Configuration Language navigation refactoring The "Configuration Language" section was becoming rather unweildy, both by having a lot of pages and by some of the pages being quite large in themselves. This is a first step towards breaking things up a little more, starting with two changes: - The "Configuration Language" navigation is now split into two sub-headings "Configuration Blocks" and "Syntax". - Some of the information about sub-blocks of the "terraform" block are now given their own pages, because their content is quite complex in itself. - "Version Constraints" is now a page in its own right, rather than this content being duplicated in slightly different forms across multiple contexts that make use of user-specified version constraints. --- website/docs/configuration/backend.html.md | 172 ++++++++++++++++++ website/docs/configuration/modules.html.md | 32 +--- website/docs/configuration/terraform.html.md | 114 +++--------- .../configuration/version-constraints.html.md | 95 ++++++++++ website/docs/internals/provider-meta.html.md | 15 +- website/layouts/docs.erb | 134 ++++++++------ 6 files changed, 397 insertions(+), 165 deletions(-) create mode 100644 website/docs/configuration/backend.html.md create mode 100644 website/docs/configuration/version-constraints.html.md diff --git a/website/docs/configuration/backend.html.md b/website/docs/configuration/backend.html.md new file mode 100644 index 000000000..35e6b0094 --- /dev/null +++ b/website/docs/configuration/backend.html.md @@ -0,0 +1,172 @@ +--- +layout: "docs" +page_title: "Backend Configuration - Configuration Language" +--- + +# Backend Configuration + +-> **Note:** This page is about Terraform 0.12 and later. For Terraform 0.11 and +earlier, see +[0.11 Configuration Language: Terraform Settings](../configuration-0-11/terraform.html). + + +Each Terraform configuration can specify a backend, which defines exactly where +and how operations are performed, where [state](/docs/state/index.html) +snapshots are stored, etc. Most non-trivial Terraform configurations configure +a remote backend so that multiple people can work with the same infrastructure. + +## Using a Backend Block + +Backends are configured with a nested `backend` block within the top-level +`terraform` block: + +```hcl +terraform { + backend "remote" { + organization = "example_corp" + + workspaces { + name = "my-app-prod" + } + } +} +``` + +There are some important limitations on backend configuration: + +- A configuration can only provide one backend block. +- A backend block cannot refer to named values (like input variables, locals, or data source attributes). + +### Backend Types + +The block label of the backend block (`"remote"`, in the example above) indicates which backend type to use. Terraform has a built-in selection of backends, and the configured backend must be available in the version of Terraform you are using. + +The arguments used in the block's body are specific to the chosen backend type; they configure where and how the backend will store the configuration's state, and in some cases configure other behavior. + +Some backends allow providing access credentials directly as part of the configuration for use in unusual situations, for pragmatic reasons. However, in normal use we _do not_ recommend including access credentials as part of the backend configuration. Instead, leave those arguments completely unset and provide credentials via the credentials files or environment variables that are conventional for the target system, as described in the documentation for each backend. + +See _[Backend Types](/docs/backends/types/index.html)_ for details about each supported backend type and its configuration arguments. + +### Default Backend + +If a configuration includes no backend block, Terraform defaults to using the `local` backend, which performs operations on the local system and stores state as a plain file in the current working directory. + +## Initialization + +Whenever a configuration's backend changes, you must run `terraform init` again +to validate and configure the backend before you can perform any plans, applies, +or state operations. + +When changing backends, Terraform will give you the option to migrate +your state to the new backend. This lets you adopt backends without losing +any existing state. + +To be extra careful, we always recommend manually backing up your state +as well. You can do this by simply copying your `terraform.tfstate` file +to another location. The initialization process should create a backup +as well, but it never hurts to be safe! + +## Partial Configuration + +You do not need to specify every required argument in the backend configuration. +Omitting certain arguments may be desirable if some arguments are provided +automatically by an automation script running Terraform. When some or all of +the arguments are omitted, we call this a _partial configuration_. + +With a partial configuration, the remaining configuration arguments must be +provided as part of +[the initialization process](/docs/backends/init.html#backend-initialization). +There are several ways to supply the remaining arguments: + + * **File**: A configuration file may be specified via the `init` command line. + To specify a file, use the `-backend-config=PATH` option when running + `terraform init`. If the file contains secrets it may be kept in + a secure data store, such as + [Vault](https://www.vaultproject.io/), in which case it must be downloaded + to the local disk before running Terraform. + + * **Command-line key/value pairs**: Key/value pairs can be specified via the + `init` command line. Note that many shells retain command-line flags in a + history file, so this isn't recommended for secrets. To specify a single + key/value pair, use the `-backend-config="KEY=VALUE"` option when running + `terraform init`. + + * **Interactively**: Terraform will interactively ask you for the required + values, unless interactive input is disabled. Terraform will not prompt for + optional values. + +If backend settings are provided in multiple locations, the top-level +settings are merged such that any command-line options override the settings +in the main configuration and then the command-line options are processed +in order, with later options overriding values set by earlier options. + +The final, merged configuration is stored on disk in the `.terraform` +directory, which should be ignored from version control. This means that +sensitive information can be omitted from version control, but it will be +present in plain text on local disk when running Terraform. + +When using partial configuration, Terraform requires at a minimum that +an empty backend configuration is specified in one of the root Terraform +configuration files, to specify the backend type. For example: + +```hcl +terraform { + backend "consul" {} +} +``` + +A backend configuration file has the contents of the `backend` block as +top-level attributes, without the need to wrap it in another `terraform` +or `backend` block: + +```hcl +address = "demo.consul.io" +path = "example_app/terraform_state" +scheme = "https" +``` + +The same settings can alternatively be specified on the command line as +follows: + +``` +$ terraform init \ + -backend-config="address=demo.consul.io" \ + -backend-config="path=example_app/terraform_state" \ + -backend-config="scheme=https" +``` + +The Consul backend also requires a Consul access token. Per the recommendation +above of omitting credentials from the configuration and using other mechanisms, +the Consul token would be provided by setting either the `CONSUL_HTTP_TOKEN` +or `CONSUL_HTTP_AUTH` environment variables. See the documentation of your +chosen backend to learn how to provide credentials to it outside of its main +configuration. + +## Changing Configuration + +You can change your backend configuration at any time. You can change +both the configuration itself as well as the type of backend (for example +from "consul" to "s3"). + +Terraform will automatically detect any changes in your configuration +and request a [reinitialization](/docs/backends/init.html). As part of +the reinitialization process, Terraform will ask if you'd like to migrate +your existing state to the new configuration. This allows you to easily +switch from one backend to another. + +If you're using multiple [workspaces](/docs/state/workspaces.html), +Terraform can copy all workspaces to the destination. If Terraform detects +you have multiple workspaces, it will ask if this is what you want to do. + +If you're just reconfiguring the same backend, Terraform will still ask if you +want to migrate your state. You can respond "no" in this scenario. + +## Unconfiguring a Backend + +If you no longer want to use any backend, you can simply remove the +configuration from the file. Terraform will detect this like any other +change and prompt you to [reinitialize](/docs/backends/init.html). + +As part of the reinitialization, Terraform will ask if you'd like to migrate +your state back down to normal local state. Once this is complete then +Terraform is back to behaving as it does by default. diff --git a/website/docs/configuration/modules.html.md b/website/docs/configuration/modules.html.md index 94bd2e3bd..2bda1a57f 100644 --- a/website/docs/configuration/modules.html.md +++ b/website/docs/configuration/modules.html.md @@ -31,7 +31,7 @@ created, and published in [the dedicated _Modules_ section](/docs/modules/index.html). You can also learn more about how to use and create modules with our hands-on [modules track on learn.hashicorp.com](https://learn.hashicorp.com/terraform/modules/modules-overview?utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS). - + ## Calling a Child Module To _call_ a module means to include the contents of that module into the @@ -114,26 +114,14 @@ module "consul" { } ``` -The `version` attribute value may either be a single explicit version or -a version constraint expression. Constraint expressions use the following -syntax to specify a _range_ of versions that are acceptable: - -* `>= 1.2.0`: version 1.2.0 or newer -* `<= 1.2.0`: version 1.2.0 or older -* `~> 1.2.0`: any non-beta version `>= 1.2.0` and `< 1.3.0`, e.g. `1.2.X` -* `~> 1.2`: any non-beta version `>= 1.2.0` and `< 2.0.0`, e.g. `1.X.Y` -* `>= 1.0.0, <= 2.0.0`: any version between 1.0.0 and 2.0.0 inclusive - -When depending on third-party modules, references to specific versions are -recommended since this ensures that updates only happen when convenient to you. - -For modules maintained within your organization, a version range strategy -may be appropriate if a semantic versioning methodology is used consistently -or if there is a well-defined release process that avoids unwanted updates. +The `version` attribute accepts a [version constraint string](./version-constraints.html). +Terraform will use the newest installed version of the module that meets the +constraint; if no acceptable versions are installed, it will download the newest +version that meets the constraint. Version constraints are supported only for modules installed from a module -registry, such as the [Terraform Registry](https://registry.terraform.io/) or -[Terraform Cloud's private module registry](/docs/cloud/registry/index.html). +registry, such as the public [Terraform Registry](https://registry.terraform.io/) +or [Terraform Cloud's private module registry](/docs/cloud/registry/index.html). Other module sources can provide their own versioning mechanisms within the source string itself, or might not support versions at all. In particular, modules sourced from local file paths do not support `version`; since @@ -146,10 +134,8 @@ Along with the `source` meta-argument described above, module blocks have some more meta-arguments that have special meaning across all modules, described in more detail in other sections: -* `version` - (Optional) A [version constraint](#module-versions) - string that specifies which versions of the referenced module are acceptable. - The newest version matching the constraint will be used. `version` is supported - only for modules retrieved from module registries. +* `version` - (Optional) A [version constraint string](./version-constraints.html) + that specifies acceptable versions of the module. Described in detail above. * `providers` - (Optional) A map whose keys are provider configuration names that are expected by child module and whose values are corresponding diff --git a/website/docs/configuration/terraform.html.md b/website/docs/configuration/terraform.html.md index 6b41b1ee2..88e6ca08e 100644 --- a/website/docs/configuration/terraform.html.md +++ b/website/docs/configuration/terraform.html.md @@ -19,7 +19,7 @@ apply your configuration. ## Terraform Block Syntax -Terraform-specific settings are gathered together into `terraform` blocks: +Terraform settings are gathered together into `terraform` blocks: ```hcl terraform { @@ -37,118 +37,59 @@ following sections. ## Configuring a Terraform Backend -The selected _backend_ for a Terraform configuration defines exactly where -and how operations are performed, where [state](/docs/state/index.html) is -stored, etc. Most non-trivial Terraform configurations will have a backend -configuration that configures a remote backend to allow collaboration within -a team. +The nested `backend` block configures which backend Terraform should use. -A backend configuration is given in a nested `backend` block within a -`terraform` block: - -```hcl -terraform { - backend "s3" { - # (backend-specific settings...) - } -} -``` - -More information on backend configuration can be found in -[the _Backends_ section](/docs/backends/index.html). +The syntax and behavior of the `backend` block is described in [Backend +Configuration](./backend.html). ## Specifying a Required Terraform Version -The `required_version` setting can be used to constrain which versions of -the Terraform CLI can be used with your configuration. If the running version of -Terraform doesn't match the constraints specified, Terraform will produce -an error and exit without taking any further actions. +The `required_version` setting accepts a [version constraint +string,](./version-constraints.html) which specifies which versions of Terraform +can be used with your configuration. -When you use [child modules](./modules.html), each module -can specify its own version requirements. The requirements of all modules -in the tree must be satisfied. +If the running version of Terraform doesn't match the constraints specified, +Terraform will produce an error and exit without taking any further actions. + +When you use [child modules](./modules.html), each module can specify its own +version requirements. The requirements of all modules in the tree must be +satisfied. Use Terraform version constraints in a collaborative environment to ensure that everyone is using a specific Terraform version, or using at least a minimum Terraform version that has behavior expected by the configuration. The `required_version` setting applies only to the version of Terraform CLI. -Various behaviors of Terraform are actually implemented by Terraform Providers, +Various behaviors of Terraform are actually implemented by Terraform providers, which are released on a cycle independent of Terraform CLI and of each other. Use [provider version constraints](./providers.html#provider-versions) to make similar constraints on which provider versions may be used. -The value for `required_version` is a string containing a comma-separated -list of constraints. Each constraint is an operator followed by a version -number, such as `> 0.12.0`. The following constraint operators are allowed: +## Specifying Provider Requirements -* `=` (or no operator): exact version equality +[inpage-source]: #specifying-provider-requirements -* `!=`: version not equal - -* `>`, `>=`, `<`, `<=`: version comparison, where "greater than" is a larger - version number - -* `~>`: pessimistic constraint operator, constraining both the oldest and - newest version allowed. For example, `~> 0.9` is equivalent to - `>= 0.9, < 1.0`, and `~> 0.8.4`, is equivalent to `>= 0.8.4, < 0.9` - -Re-usable modules should constrain only the minimum allowed version, such -as `>= 0.12.0`. This specifies the earliest version that the module is -compatible with while leaving the user of the module flexibility to upgrade -to newer versions of Terraform without altering the module. - -## Specifying Required Provider Versions - -The `required_providers` setting is a map specifying a version constraint for -each provider required by your configuration. - -```hcl -terraform { - required_providers { - aws = ">= 2.7.0" - } -} -``` - -Version constraint strings within the `required_providers` block use the -same version constraint syntax as for -[the `required_version` argument](#specifying-a-required-terraform-version) -described above. - -When a configuration contains multiple version constraints for a single -provider -- for example, if you're using multiple modules and each one has -its own constraint -- _all_ of the constraints must hold to select a single -provider version for the whole configuration. - -Re-usable modules should constrain only the minimum allowed version, such -as `>= 1.0.0`. This specifies the earliest version that the module is -compatible with while leaving the user of the module flexibility to upgrade -to newer versions of the provider without altering the module. - -Root modules should use a `~>` constraint to set both a lower and upper bound -on versions for each provider they depend on, as described in -[Provider Versions](providers.html#provider-versions). - -An alternate syntax is also supported, but not intended for use at this time. -It exists to support future enhancements. +The `required_providers` block specifies all of the providers required by the +current module. ```hcl terraform { required_providers { aws = { version = ">= 2.7.0" + source = "hashicorp/aws" } } } ``` +For more information, see [Provider Requirements](provider-requirements.html). + ## Experimental Language Features -From time to time the Terraform team will introduce new language features -initially via an opt-in experiment, so that the community can try the new -feature and give feedback on it prior to it becoming a backward-compatibility -constraint. +The Terraform team will sometimes introduce new language features initially via +an opt-in experiment, so that the community can try the new feature and give +feedback on it prior to it becoming a backward-compatibility constraint. In releases where experimental features are available, you can enable them on a per-module basis by setting the `experiments` argument inside a `terraform` @@ -184,6 +125,7 @@ if any, are available in a particular Terraform release. The `terraform` block can have a nested `provider_meta` block for each provider a module is using, if the provider defines a schema for it. This -allows the provider to receive module-specific information. No interpolations -are performed on this block. For more information, see the -[`provider_meta` page](/docs/internals/provider-meta.html). +allows the provider to receive module-specific information, and is primarily +intended for modules distributed by the same vendor as the associated provider. + +For more information, see [Provider Metadata](/docs/internals/provider-meta.html). diff --git a/website/docs/configuration/version-constraints.html.md b/website/docs/configuration/version-constraints.html.md new file mode 100644 index 000000000..695580154 --- /dev/null +++ b/website/docs/configuration/version-constraints.html.md @@ -0,0 +1,95 @@ +--- +layout: "docs" +page_title: "Version Constraints - Configuration Language" +--- + +# Version Constraints + +Anywhere that Terraform lets you specify a range of acceptable versions for +something, it expects a specially formatted string known as a version +constraint. Version constraints are used when configuring: + +- [Modules](./modules.html) +- [Provider requirements](./provider-requirements.html) +- [The `required_version` setting](./terraform.html#specifying-a-required-terraform-version) in the `terraform` block. + +## Version Constraint Syntax + +Terraform's syntax for version constraints is very similar to the syntax used by +other dependency management systems like Bundler and NPM. + +```hcl +version = ">= 1.2.0, < 2.0.0" +``` + +A version constraint is a [string literal](./expressions.html#string-literals) +containing one or more conditions, which are separated by commas. + +Each condition consists of an operator and a version number. + +Version numbers should be a series of numbers separated by periods (like +`1.2.0`), optionally with a suffix to indicate a beta release. + +The following operators are valid: + +- `=` (or no operator): Allows only one exact version number. Cannot be combined + with other conditions. + +- `!=`: Excludes an exact version number. + +- `>`, `>=`, `<`, `<=`: Comparisons against a specified version, allowing + versions for which the comparison is true. "Greater-than" requests newer + versions, and "less-than" requests older versions. + +- `~>`: Allows the specified version, plus newer versions that only + increase the _most specific_ segment of the specified version number. For + example, `~> 0.9` is equivalent to `>= 0.9, < 1.0`, and `~> 0.8.4`, is + equivalent to `>= 0.8.4, < 0.9`. This is usually called the pessimistic + constraint operator. + +## Version Constraint Behavior + +A version number that meets every applicable constraint is considered acceptable. + +Terraform consults version constraints to determine whether it has acceptable +versions of itself, any required provider plugins, and any required modules. For +plugins and modules, it will use the newest installed version that meets the +applicable constraints. + +If Terraform doesn't have an acceptable version of a required plugin or module, +it will attempt to download the newest version that meets the applicable +constraints. + +If Terraform isn't able to obtain acceptable versions of external dependencies, +or if it doesn't have an acceptable version of itself, it won't proceed with any +plans, applies, or state manipulation actions. + +Both the root module and any child module can constrain the acceptable versions +of Terraform and any providers they use. Terraform considers these constraints +equal, and will only proceed if all of them can be met. + +A prerelease version is a version number that contains a suffix introduced by +a dash, like `1.2.0-beta`. A prerelease version can be selected only by an +_exact_ version constraint (the `=` operator or no operator). Prerelease +versions do not match inexact operators such as `>=`, `~>`, etc. + +## Best Practices + +### Module Versions + +- When depending on third-party modules, require specific versions to ensure + that updates only happen when convenient to you. + +- For modules maintained within your organization, specifying version ranges + may be appropriate if semantic versioning is used consistently or if there is + a well-defined release process that avoids unwanted updates. + +### Terraform Core and Provider Versions + +- Reusable modules should constrain only their minimum allowed versions of + Terraform and providers, such as `>= 0.12.0`. This helps avoid known + incompatibilities, while allowing the user of the module flexibility to + upgrade to newer versions of Terraform without altering the module. + +- Root modules should use a `~>` constraint to set both a lower and upper bound + on versions for each provider they depend on. diff --git a/website/docs/internals/provider-meta.html.md b/website/docs/internals/provider-meta.html.md index 9559b6cd5..9213c640d 100644 --- a/website/docs/internals/provider-meta.html.md +++ b/website/docs/internals/provider-meta.html.md @@ -10,8 +10,19 @@ description: |- In some situations it's beneficial for a provider to offer an interface through which modules can pass it information unrelated to the resources -in the module, but scoped on a per-module basis. The provider metadata -functionality allows a provider to do this in a straightforward way. +in the module, but scoped on a per-module basis. + +Provider Metadata allows a provider to declare metadata fields it expects, +which individual modules can then populate independently of any provider +configuration. While provider configurations are often shared between modules, +provider metadata is always module-specific. + +Provider Metadata is intended primarily for the situation where an official +module is developed by the same vendor that produced the provider it is +intended to work with, to allow the vendor to indirectly obtain usage +statistics for each module via the provider. For that reason, this +documentation is presented from the perspective of the provider developer +rather than the module developer. ~> **Advanced Topic!** This page covers technical details of Terraform. You don't need to understand these details to diff --git a/website/layouts/docs.erb b/website/layouts/docs.erb index 9671b3d49..853f224ef 100644 --- a/website/layouts/docs.erb +++ b/website/layouts/docs.erb @@ -9,65 +9,91 @@ > 0.12 and Newer