Skip to content

Commit

Permalink
Update contributor docs to recommend dev overrides (#7130)
Browse files Browse the repository at this point in the history
* Update contributor docs to recommend dev overrides

* Revert `make provider` to `make build` in docs about building binaries

* Update docs/content/docs/getting-started/use-built-provider.md

Co-authored-by: Stephen Lewis (Burrows) <stephen.r.burrows@gmail.com>

* Update docs/content/docs/getting-started/use-built-provider.md

Co-authored-by: Stephen Lewis (Burrows) <stephen.r.burrows@gmail.com>

* Replace example username with gender neutral example

* Remove unneeded section, update opening paragraph(s) with URL from unneeded section

* Add warning about developer overrides needing v0.14+

* Return section advising how to clean up a filesystem mirror, and debug using TF_LOG env

* Update docs/content/docs/getting-started/use-built-provider.md

Co-authored-by: Riley Karson <rileykarson@google.com>

* Apply suggestions from code review - `make provider`

Co-authored-by: Stephen Lewis (Burrows) <stephen.r.burrows@gmail.com>

* Revert `make provider` to `make build` in docs about building binaries

Co-authored-by: Stephen Lewis (Burrows) <stephen.r.burrows@gmail.com>
Co-authored-by: Riley Karson <rileykarson@google.com>
  • Loading branch information
3 people authored Jan 25, 2023
1 parent dfc9421 commit 0ae27f3
Showing 1 changed file with 155 additions and 32 deletions.
187 changes: 155 additions & 32 deletions docs/content/docs/getting-started/use-built-provider.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,75 +11,198 @@ weight: 40

Sometimes, for example for manual testing, you may want to build the provider from source and use it with `terraform`.

## Developer Overrides

{{< hint info >}}
**Note:** Developer overrides are only available in Terraform v0.14 and later.
{{< /hint >}}

By default Terraform will download providers from the [public Registry](https://registry.terraform.io/), but there are several ways to override this behaviour and use providers from other sources. HashiCorp recommends developers use [development overrides](https://developer.hashicorp.com/terraform/plugin/debugging#terraform-cli-development-overrides) when debugging code changes in a provider.

Developer overrides are defined in an explicit [CLI configuration file](https://developer.hashicorp.com/terraform/cli/config/config-file#cli-configuration-file-terraformrc-or-terraform-rc). They allow you to use locally-built versions of providers without needing to change your Terraform configuration files or needing to run `terraform init`. There are also other features such as explicit warnings when overrides are in effect.

In the sections below we describe how to create a Terraform CLI configuration file, and how to make the CLI use the file via an environment variable.

## Setup

Choose your architecture below.

{{< details "Mac ARM64" >}}
{{< details "Mac (ARM64 and AMD64), Linux AMD64" >}}

First, you need to find the location where built provider binaries are created. To do this, run this command and make a note of the path value:

```bash
mkdir -p ~/.terraform.d/plugins/registry.terraform.io/hashicorp/google/9.0.0/darwin_arm64
mkdir -p ~/.terraform.d/plugins/registry.terraform.io/hashicorp/google-beta/9.0.0/darwin_arm64
ln -s $GOPATH/bin/terraform-provider-google ~/.terraform.d/plugins/registry.terraform.io/hashicorp/google/9.0.0/darwin_arm64/terraform-provider-google_v9.0.0
ln -s $GOPATH/bin/terraform-provider-google-beta ~/.terraform.d/plugins/registry.terraform.io/hashicorp/google-beta/9.0.0/darwin_arm64/terraform-provider-google-beta_v9.0.0
echo $GOPATH
```
{{< /details >}}

Next, create an empty configuration file. This could be in your `$HOME` directory or in a project directory; location does not matter. The extension `.tfrc` is required but the file name can be whatever you choose.

{{< details "Mac AMD64" >}}
```bash
mkdir -p ~/.terraform.d/plugins/registry.terraform.io/hashicorp/google/9.0.0/darwin_amd64
mkdir -p ~/.terraform.d/plugins/registry.terraform.io/hashicorp/google-beta/9.0.0/darwin_amd64
ln -s $GOPATH/bin/terraform-provider-google ~/.terraform.d/plugins/registry.terraform.io/hashicorp/google/9.0.0/darwin_amd64/terraform-provider-google_v9.0.0
ln -s $GOPATH/bin/terraform-provider-google-beta ~/.terraform.d/plugins/registry.terraform.io/hashicorp/google-beta/9.0.0/darwin_amd64/terraform-provider-google-beta_v9.0.0
# create an empty file
touch ~/tf-dev-override.tfrc

# open the file with a text editor of your choice, e.g:
vi ~/tf-dev-override.tfrc
```
{{< /details >}}

{{< details "Linux AMD64" >}}
```bash
mkdir -p ~/.terraform.d/plugins/registry.terraform.io/hashicorp/google/9.0.0/linux_amd64
mkdir -p ~/.terraform.d/plugins/registry.terraform.io/hashicorp/google-beta/9.0.0/linux_amd64
ln -s $GOPATH/bin/terraform-provider-google ~/.terraform.d/plugins/registry.terraform.io/hashicorp/google/9.0.0/linux_amd64/terraform-provider-google_v9.0.0
ln -s $GOPATH/bin/terraform-provider-google-beta ~/.terraform.d/plugins/registry.terraform.io/hashicorp/google-beta/9.0.0/linux_amd64/terraform-provider-google-beta_v9.0.0
Open the empty file with a text editor and paste in these contents:

```hcl
provider_installation {
# Developer overrides will stop Terraform from downloading the listed
# providers their origin provider registries.
dev_overrides {
"hashicorp/google" = "<REPLACE-ME>/bin"
"hashicorp/google-beta" = "<REPLACE-ME>/bin"
}
# For all other providers, install them directly from their origin provider
# registries as normal. If you omit this, Terraform will _only_ use
# the dev_overrides block, and so no other providers will be available.
direct {}
}
```

Edit the file to replace `<REPLACE-ME>` with the output you saved from the first `echo` command, making sure to keep `/bin` at the end of the path. The full path is required and environment variables cannot be used. For example, `/Users/MyUserName/go/bin` is a valid path for a user called `MyUserName`.

Finally, save the file.

{{< /details >}}

{{< details "Other: substitute your architecture" >}}
{{< details "Windows (Vista and above)" >}}

First, you need to find the location where built provider binaries are created. To do this, run this command and make a note of the path value:

```bash
mkdir -p ~/.terraform.d/plugins/registry.terraform.io/hashicorp/google/9.0.0/myarch_amd64
mkdir -p ~/.terraform.d/plugins/registry.terraform.io/hashicorp/google-beta/9.0.0/myarch_amd64
ln -s $GOPATH/bin/terraform-provider-google ~/.terraform.d/plugins/registry.terraform.io/hashicorp/google/9.0.0/myarch_amd64/terraform-provider-google_v9.0.0
ln -s $GOPATH/bin/terraform-provider-google-beta ~/.terraform.d/plugins/registry.terraform.io/hashicorp/google-beta/9.0.0/myarch_amd64/terraform-provider-google-beta_v9.0.0
echo %GOPATH%
```

Next, create an empty configuration file. The location does not matter and could be in your home directory or a specific project directory. The extension `.tfrc` is required but the file name can be whatever you choose.

If you are unsure where to put the file, put it in the `%APPDATA%` directory (use `$env:APPDATA` in PowerShell to find its location on your system).

```powershell
# create an empty file
type nul > "$($env:APPDATA)\tf-dev-override.tfrc"
# open the file with a text editor of your choice, e.g:
notepad "$($env:APPDATA)\tf-dev-override.tfrc"
```

Open the empty file with a text editor and paste in these contents:

```hcl
provider_installation {
# Developer overrides will stop Terraform from downloading the listed
# providers their origin provider registries.
dev_overrides {
"hashicorp/google" = "<REPLACE-ME>\bin"
"hashicorp/google-beta" = "<REPLACE-ME>\bin"
}
# For all other providers, install them directly from their origin provider
# registries as normal. If you omit this, Terraform will _only_ use
# the dev_overrides block, and so no other providers will be available.
direct {}
}
```

Edit the file to replace `<REPLACE-ME>` with the output you saved from the first `echo` command, making sure to keep `\bin` at the end of the path. The full path is required and environment variables cannot be used. For example, `C:\Users\MyUserName\go\bin` is a valid path for a user called `MyUserName`.

Finally, save the file.

{{< /details >}}

Once this setup is complete, terraform will automatically use the binaries generated by the `make provider` commands in the `terraform-provider-google` and `terraform-provider-google-beta` repositories instead of downloading the latest versions.
This CLI configuration file you created in the steps above will allow Terraform to automatically use the binaries generated by the `make build` commands in the `terraform-provider-google` and `terraform-provider-google-beta` repositories instead of downloading the latest versions. All other providers will continue to be downloaded from the public Registry as normal.

## Build provider

```bash
# ga provider
cd $GOPATH/src/github.com/hashicorp/terraform-provider-google
make provider
make build

# beta provider
cd $GOPATH/src/github.com/hashicorp/terraform-provider-google-beta
make provider
make build
```

## Cleanup
## Using Terraform CLI developer overrides

To stop using the local provider binary, you can run:
To make Terraform use the configuration file you created, you need to set the `TF_CLI_CONFIG_FILE` environment variable to be a string containing the path to the configuration file ([see the documentation here](https://developer.hashicorp.com/terraform/cli/config/environment-variables#tf_cli_config_file)). The path can be either a relative or absolute path.

Assuming that a configuration file was created at `~/tf-dev-override.tfrc`, you can either export the environment variable or set it explicitly for each `terraform` command:

```bash
rm -rf ~/.terraform.d/plugins/registry.terraform.io/hashicorp/
# either export the environment variable for your session
export TF_CLI_CONFIG_FILE="~/tf-dev-override.tfrc"

# OR, set the environment variable value per command
TF_CLI_CONFIG_FILE="~/tf-dev-override.tfrc" terraform plan
```

To check that the developer override is working, run a `terraform plan` command and look for a warning near the start of the terminal output that looks like the example below. It is not necessary to run the terraform init command to use development overrides.

```
│ Warning: Provider development overrides are in effect
│ The following provider development overrides are set in the CLI configuration:
│ - hashicorp/google in /Users/MyUserName/go/bin
│ - hashicorp/google-beta in /Users/MyUserName/go/bin
│ The behavior may therefore not match any released version of the provider and applying
│ changes may cause the state to become incompatible with published releases.
```

{{< hint info >}}
**Note:** Developer overrides work without you needing to alter your Terraform configuration in any way.
{{< /hint >}}

## Download production providers

When in this mode, Terraform will be unable to pull the `google` and `google-beta` providers from the registry using `terraform init`, even if a version constraint requires them. However, providers downloaded to the discovery directory may be used by `init`. To download providers to the discovery directory, run `terraform providers mirror ~/.terraform.d/plugins` from your configuration's directory prior to running `terraform init`.
To stop using developer overrides, unset the `TF_CLI_CONFIG_FILE` environment variable or stop setting it in the commands you are executing.

This will then let Terraform resume normal behaviour of pulling published provider versions from the public Registry. Any version constraints in your Terraform configuration will come back into effect. Also, you may need to run `terraform init` to download the required version of the provider into your project directory if you haven't already.

## Alternative: using a global CLI configuration file

If you do not want to use the `TF_CLI_CONFIG_FILE` environment variable, as described above, you can instead create a global version of the CLI configuration file. This configuration will be used automatically by Terraform. To do this, follow [the guidance in the official documentation](https://developer.hashicorp.com/terraform/cli/config/config-file#locations).

In this scenario you will need to remember to edit this file to swap between using developer overrides and using the production provider versions.

## Possible problems

Filesystem mirrors (particularly "[_implicit_ filesystem mirrors](https://developer.hashicorp.com/terraform/cli/config/config-file#implied-local-mirror-directories)") are used automatically by Terraform, so can interfere with the expected behaviour of Terraform if you're not aware they're present.

To stop using the filesystem mirror, you can run:

```bash
rm -rf ~/.terraform.d/plugins/registry.terraform.io/hashicorp/
```

Another way to debug this is to run a Terraform command with the `TF_LOG` environment variable set to `TRACE` . Then, look for a log line similar to the below:

```bash
[TRACE] getproviders.SearchLocalDirectory: found registry.terraform.io/hashicorp/google vX.X.X for darwin_arm64 at /Users/MyUserName/.terraform.d/plugins/registry.terraform.io/hashicorp/google/xxx
```

## More information

For more information, check out Hashicorp's documentation on the [0.13+ filesystem layout](https://www.terraform.io/upgrade-guides/0-13.html#new-filesystem-layout-for-local-copies-of-providers).
### Filesystem mirrors

An alternative to developer overrides is to use filesystem mirrors, where Terraform can use locally built providers or published providers that you have downloaded to your local disk. More information about this approach is in the expandable section below.

{{< details "More information" >}}

Filesystem mirrors can used explicitly or implicitly by Terraform. Explicit filesystem mirrors can be [defined via the CLI configuration file](https://developer.hashicorp.com/terraform/cli/config/config-file#filesystem_mirror). In contrast, once [implicit filesystem mirrors](https://developer.hashicorp.com/terraform/cli/config/config-file#implied-local-mirror-directories) are created by a user they are discovered and used by Terraform automatically.

Filesystem mirrors require providers' files to be saved with specific paths for them to work correctly. To help with this, you can use the [`terraform providers mirror` command](https://developer.hashicorp.com/terraform/cli/commands/providers/mirror) to download a published provider to your local filesystem with the required file path.

Implied filesystem mirrors require manual cleanup if you want to revert back to using providers downloaded from the public Registry, and if an implied filesystem mirror is in place that a user is unaware of it can lead to confusing behaviour that is hard to debug. Other disadvantages compared to developer overrides include:
- No warning in terminal output letting you know when your local files are in use.
- Need to set a version number for your local version of the provider which is compatible with your Terraform configuration's version constraints
- Setup and cleanup required each time you swap to and from using them

If multiple versions are available in a plugin directory (for example after `terraform providers mirror` is used), Terraform will pick the most up-to-date provider version within version constraints. As such, we recommend using a version that is several major versions ahead for your local copy of the provider, such as `9.0.0`.
{{< /details >}}

0 comments on commit 0ae27f3

Please sign in to comment.