diff --git a/README.md b/README.md index 2c2375a2b..87a038494 100644 --- a/README.md +++ b/README.md @@ -551,6 +551,55 @@ Example: **Warning:** If you use Terraform workspaces, DO NOT use this workaround ([details](https://github.com/antonbabenko/pre-commit-terraform/issues/203#issuecomment-918791847)). Wait to [`force-init`](https://github.com/antonbabenko/pre-commit-terraform/issues/224) option implementation. +5. `terraform_validate` in a repo with Terraform module, written using Terraform 0.15+ and which uses provider `configuration_aliases` ([Provider Aliases Within Modules](https://www.terraform.io/language/modules/develop/providers#provider-aliases-within-modules)), errors out. + + When running the hook against Terraform code where you have provider `configuration_aliases` defined in a `required_providers` configuration block, terraform will throw an error like: + > + > + > Error: Provider configuration not present + > To work with its original provider configuration at provider["registry.terraform.io/hashicorp/aws"]. is required, but it has been removed. This occurs when a provider configuration is removed while + > objects created by that provider still exist in the state. Re-add the provider configuration to destroy , after which you can remove the provider configuration again. + + This is a [known issue](https://github.com/hashicorp/terraform/issues/28490) with Terraform and how providers are initialized in Terraform 0.15 and later. To work around this you can add an `exclude` parameter to the configuration of `terraform_validate` hook like this: + ```yaml + - id: terraform_validate + exclude: [^/]+$ + ``` + This will exclude the root directory from being processed by this hook. Then add a subdirectory like "examples" or "tests" and put an example implementation in place that defines the providers with the proper aliases, and this will give you validation of your module through the example. If instead you are using this with multiple modules in one repository you'll want to set the path prefix in the regular expression, such as `exclude: modules/offendingmodule/[^/]+$`. + + Alternately, you can use [terraform-config-inspect](https://github.com/hashicorp/terraform-config-inspect) and use a variant of [this script](https://github.com/bendrucker/terraform-configuration-aliases-action/blob/main/providers.sh) to generate a providers file at runtime: + + ```bash + terraform-config-inspect --json . | jq -r ' + [.required_providers[].aliases] + | flatten + | del(.[] | select(. == null)) + | reduce .[] as $entry ( + {}; + .provider[$entry.name] //= [] | .provider[$entry.name] += [{"alias": $entry.alias}] + ) + ' | tee aliased-providers.tf.json + ``` + + Save it as `.generate-providers.sh` in the root of your repository and add a `pre-commit` hook to run it before all other hooks, like so: + ```yaml + - repos: + - repo: local + hooks: + - id: generate-terraform-providers + name: generate-terraform-providers + require_serial: true + entry: .generate-providers.sh + language: script + files: \.tf(vars)?$ + pass_filenames: false + + - repo: https://github.com/pre-commit/pre-commit-hooks + [...] + ``` + + **Note:** The latter method will leave an "aliased-providers.tf.json" file in your repo. You will either want to automate a way to clean this up or add it to your `.gitignore` or both. + ### terrascan 1. `terrascan` supports custom arguments so you can pass supported flags like `--non-recursive` and `--policy-type` to disable recursive inspection and set the policy type respectively: