When i am doing terraform init commands, TF is not having the tfstate ( my tfstate file is in s3 bucket ). Also i am not able to see the terraform backend-config file inside the .terraform folder.
I am using terraform 0.10.4 version
Outputs:
$ terraform --version
Terraform v0.10.4
$ terraform init \
-lock="true"
-backend-config="bucket=$TF_STATE_BUCKET"
-backend-config="key=$TF_STATE_KEY"
-backend-config="dynamodb_table=$TF_LOCK_TABLE"
-backend-config="region=$AWS_REGION"
-backend-config="profile=$AWS_PROFILE"
-backend-config="encrypt=true"
.
Downloading modules...
Get: git::ssh://XXXXXXXXXXXXXXXXX/add/tf-vpc.git?ref=1.0.1
Get: git::ssh://XXXXXXXXXXXXXXXXX/add/tf-ec-redis.git?ref=1.1.3
Get: git::ssh://XXXXXXXXXXXXXXXXX/add/tf-rds-pg.git?ref=1.3.0
Initializing provider plugins...
Checking for available provider plugins on https://releases.hashicorp.com...
Downloading plugin for provider "aws" (0.1.4)...
The following providers do not have any version constraints in configuration, so the latest version was installed.
To prevent automatic upgrades to new major versions that may contain breaking changes, it is recommended to add version = "..." constraints to the corresponding provider blocks in configuration, with the constraint strings suggested below.
provider.aws: version = "~> 0.1"
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure. All Terraform commands should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other commands will detect it and remind you to do so if necessary.
$ ll -al .terraform/
total 8
drwxr-xr-x 1 XXXXX 1049089 0 Sep 12 18:10 modules/
drwxr-xr-x 1 XXXXX 1049089 0 Sep 12 18:10 plugins/
In present location TF will take the backup of the s3-tfstate file, but it's not there.
This is expect behaviour after 0.9.x. The local tfstate file at .terraform/terraform.tfstate is almost an empty file. The only change is the serial number in it. It keeps increasing.
"serial": 1,
If you don't run terraform apply, the remote tfstate file will not be updated. If you never run terraform apply, the remote tfstate file is not exist.
So try to make some changes, then check the remote tfstate file (in your case, it is s3://$TF_STATE_BUCKET/$TF_STATE_KEY), you should see the difference.
Related
I am stuck in a path where when I run terraform init. the provider is not getting downloaded and it gives me no error. I am using the main.tf file and in it, I have provider "azurerm" syntax only. So when I run the terraform init I get the below output only and I see nowhere the terraform provider file getting initialized or getting downloaded. Logged in and authenticated to Azure login page too.
Terraform Code> terraform init
Initializing the backend...
Initializing provider plugins...
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Terraform creates a hidden folder to store the provider. Make sure you set your OS permissions to see hidden files and folders.
From the documentation:
A hidden .terraform directory, which Terraform uses to manage cached provider plugins and modules, record which workspace is currently active, and record the last known backend configuration in case it needs to migrate state on the next run. This directory is automatically managed by Terraform, and is created during initialization.
The expectation is that when running a terragrunt run-all apply from the root directory, a provider.tf file will be created in the sub directories. I've verified my backend is able to talk to my azure storage account and it will create a terraform.tfstate file there. I expect a provider.tf file to appear under each "service#" folder. I'm extremely new to terragrunt. This is my first exercise with it. I am not actually trying to deploy any terraform resources. Just have the provider.tf file created in my sub directories. TF version is 1.1.5. Terragrunt version is 0.36.1.
my folder structure
tfpractice
├───terragrunt.hcl
├───environment_vars.yaml
├───dev
│ ├───service1
│ ├───terragrunt.hcl
│ └───service2
│ ├───terragrunt.hcl
└───prod
├───service1
│ ├───terragrunt.hcl
└───service2
│ ├───terragrunt.hcl
root terragrunt.hcl config
# Generate provider configuration for all child directories
generate "provider" {
path = "provider.tf"
if_exists = "overwrite"
contents = <<EOF
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "2.94.0"
}
}
backend "azurerm" {}
}
provider "azurerm" {
features {}
}
EOF
}
# Remote backend settings for all child directories
remote_state {
backend = "azurerm"
config = {
resource_group_name = local.env_vars.resource_group_name
storage_account_name = local.env_vars.storage_account_name
container_name = local.env_vars.container_name
key = "${path_relative_to_include()}/terraform.tfstate"
}
}
# Collect values from environment_vars.yaml and set as local variables
locals {
env_vars = yamldecode(file("environment_vars.yaml"))
}
environment_vars.yaml config
resource_group_name: "my-tf-test"
storage_account_name: "mystorage"
container_name: "tfstate"
terragrunt.hcl config in the service# folders
# Collect values from parent environment_vars.yaml file and set as local variables
locals {
env_vars = yamldecode(file(find_in_parent_folders("environment_vars.yaml")))
}
# Include all settings from the root terragrunt.hcl file
include {
path = find_in_parent_folders()
}
When i run the terragrunt run-all apply this is the output
Are you sure you want to run 'terragrunt apply' in each folder of the stack described above? (y/n) y
Initializing the backend...
Initializing the backend...
Initializing the backend...
Initializing the backend...
Initializing provider plugins...
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Initializing provider plugins...
Initializing provider plugins...
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Initializing provider plugins...
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
No changes. Your infrastructure matches the configuration.
No changes. Your infrastructure matches the configuration.
Terraform has compared your real infrastructure against your configuration
and found no differences, so no changes are needed.
No changes. Your infrastructure matches the configuration.
Terraform has compared your real infrastructure against your configuration
and found no differences, so no changes are needed.
No changes. Your infrastructure matches the configuration.
Terraform has compared your real infrastructure against your configuration
and found no differences, so no changes are needed.
Terraform has compared your real infrastructure against your configuration
and found no differences, so no changes are needed.
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
It looks successful, however NO provider.tf files show up in ANY directory. Not even root. It just creates a terraform.tfstate file under the service# directories.
But...if I run a terragrunt init from the root directory, it will create the provider.tf file as expected in the root directory. This does NOT work in the service# directories although the terragrunt init is successful.
What am I missing? This is the most basic terragrunt use case, but the examples lead me to believe this should just work.
I got it to work, but the terragrunt run-all apply command doesn't work at all. Instead, at the root I have to run terragrunt apply. If you don't at the root, then all sub folders get grouped together rather than in a dev/prod sub folder. Then I have to go to every sub folder and run this again. It's the only way i've gotten it to work.
If I run terraform -version from the directory that I ran terraform init, terraform correctly finds the plugins.
But if I run terraform -version from any other directory, terraform does NOT find any provider plugins.
My ~/.terraformrc file looks like this:
provider_installation {
filesystem_mirror {
path = "/.terraform/providers"
include = ["registry.terraform.io/hashicorp/*"]
}
}
Inside that directory, I have the aws provider binary (it was placed there by terraform init, so I know the directory structure is correct:
/.terraform/providers/registry.terraform.io/hashicorp/aws/3.55.0/linux_amd64/terraform-provider-aws_v3.55.0_x5
When I cd to /, terraform correctly finds the provider:
# terraform -version
Terraform v1.0.6
on linux_amd64
+ provider registry.terraform.io/hashicorp/aws v3.55.0
But if I cd to /tmp, terraform does NOT find the provider:
/tmp # terraform -version
Terraform v1.0.6
on linux_amd64
So that tells me there is something not right with the .terraformrc file.
If I run that with TRACE, it doesn't say much:
2021-09-08T03:01:30.336Z [DEBUG] Attempting to open CLI config file: /root/.terraformrc
2021-09-08T03:01:30.336Z [INFO] Loading CLI configuration from /root/.terraformrc
2021-09-08T03:01:30.336Z [DEBUG] Explicit provider installation configuration is set
2021-09-08T03:01:30.336Z [TRACE] Selected provider installation method cliconfig.ProviderInstallationFilesystemMirror("/.terraform/providers") with includes [registry.terraform.io/hashicorp/*] and excludes []
2021-09-08T03:01:30.337Z [INFO] CLI command args: []string{"version", "-version"}
Terraform v1.0.6
on linux_amd64
How can I tell terraform to look in `/.terraform/providers" for all of it's providers?
I think in your investigations here you are confusing two different concepts for Terraform provider installation: a local filesystem mirror (which you've configured in your CLI configuration), and your current working directory's provider cache (which is where terraform init installs the providers for the current working directory).
A local filesystem mirror happens to support a similar directory structure to a provider cache directory, and so what you've achieved by running Terraform in the root directory is to trick Terraform into thinking that your local mirror is the local cache directory for that working directory. It doesn't work anywhere else because in that case these two separate directories are truly separate, which is the expected way to use Terraform.
The other relevant thing to know in what you tried here is that terraform version will only show providers that are already installed and activated by terraform init. Again, because you tricked Terraform into treating your filesystem mirror as the local cache directory it happened to find the required hashicorp/aws plugin there, but when you ran it elsewhere there was no local cache directory and so it returned nothing.
You mentioned that your goal is to have Terraform look for providers only in your local filesystem directory, in /.terraform. I'll note that a dot file in the root of your filesystem is a rather unusual place to keep a local filesystem mirror, but I'll use that path here anyway since you asked about it in your question.
First, configure the filesystem mirror as you already did, and also configure the "direct" installation method (installing from the origin registry) to exclude those same providers:
provider_installation {
filesystem_mirror {
path = "/.terraform/providers"
include = ["registry.terraform.io/hashicorp/*"]
}
direct {
exclude = ["registry.terraform.io/hashicorp/*"]
}
}
The above means that for any provider in the hashicorp namespace on the public registry, Terraform will only look in /.terraform. For all other providers, Terraform will contact the origin registry in the usual way and try to download the provider over the network.
With that configuration in place, change your shell's current working directory to be the root directory of your configuration, which is the directory containing your root set of .tf files. To initialize that as a working directory, which will install all of the needed providers and external modules, run:
terraform init
Terraform will then read the configuration to learn which providers it requires, and will automatically install each of them in turn. Because of the CLI configuration above, Terraform will not contact the origin registry for any of the hashicorp namespace providers, and will instead expect them to already be present in the mirror directory. Regardless of whether each provider was found in the local filesystem mirror or directly in the origin registry, they'll all then be cached in the .terraform/providers subdirectory of your working directory, which is the local cache directory.
You specifically asked about preventing Terraform from accessing the origin registry at all here and so I've answered with that in mind. However, a more common request is to have Terraform contact the registry the first time it installs each provider and then cache the result locally for future installation. If that is what you want to achieve here then you should enable the global provider plugin cache instead.
In that case, the global cache directory becomes a secondary read-through cache for the local cache directory I was describing above. When installing new providers to the local cache directory, Terraform will first check the global cache directory and either copy or symlink (depending on whether your system can support symlinks) the global cache entry into the local cache directory, and thus avoid re-downloading the same package from the registry again.
I'm trying to deploy a bitbucket pipeline using terraform v0.14.3 to create resources in google cloud. after running terraform command, the pipeline fails with this error:
Error: Invalid legacy provider address
This configuration or its associated state refers to the unqualified provider
"google".
You must complete the Terraform 0.13 upgrade process before upgrading to later
versions.
We updated our local version of terraform to v.0.13.0 and then ran: terraform 0.13upgrade as referenced in this guide: https://www.terraform.io/upgrade-guides/0-13.html. A versions.tf file was generated requiring terraform version >=0.13 and our required provider block now looks like this:
terraform {
backend "gcs" {
bucket = "some-bucket"
prefix = "terraform/state"
credentials = "key.json" #this is just a bitbucket pipeline variable
}
required_providers {
google = {
source = "hashicorp/google"
version = "~> 2.20.0"
}
}
}
provider "google" {
project = var.project_ID
credentials = "key.json"
region = var.project_region
}
We still get the same error when initiating the bitbucket pipeline. Does anyone know how to get past this error? Thanks in advance.
Solution
If you are using a newer version of Terraform, such as v0.14.x, you should:
use the replace-provider subcommand
terraform state replace-provider \
-auto-approve \
"registry.terraform.io/-/google" \
"hashicorp/google"
#=>
Terraform will perform the following actions:
~ Updating provider:
- registry.terraform.io/-/google
+ registry.terraform.io/hashicorp/google
Changing x resources:
. . .
Successfully replaced provider for x resources.
initialize Terraform again:
terraform init
#=>
Initializing the backend...
Initializing provider plugins...
- Reusing previous version of hashicorp/google from the dependency lock file
- Using previously-installed hashicorp/google vx.xx.x
Terraform has been successfully initialized!
You may now begin working with Terraform. Try . . .
This should take care of installing the provider.
Explanation
Terraform only supports upgrades from one major feature upgrade at a time. Your older state file was, more than likely, created using a version earlier than v0.13.x.
If you did not run the apply command before you upgraded your Terraform version, you can expect this error: the upgrade from v0.13.x to v0.14.x was not complete.
You can find more information here.
in our case, we were on aws and had similar error
...
Error: Invalid legacy provider address
This configuration or its associated state refers to the unqualified provider
"aws".
the steps to resolve were :
ensure syntax was upgraded by running terraform init again
check the warnings and resolve them
and finally updating the statefile with following method.
# update provider in state file
terraform state replace-provider -- -/aws hashicorp/aws
# reinit
terraform init
specific to ops problem, if issue still occurs, verify access to the bucket location from local and from pipeline. also verify the version of terraform running in pipeline. depending on configuration it may be the remote statefile is/can not be updated.
Same issue for me. I ran:
terraform providers
That gave me:
Providers required by configuration:
registry.terraform.io/hashicorp/google
Providers required by state:
registry.terraform.io/-/google
So I ran:
terraform state replace-provider registry.terraform.io/-/google registry.terraform.io/hashicorp/google
That did the trick.
To add on, I had installed terraform 0.14.6 but the state seemed to be stuck in 0.12. In my case I had 3 references that were off, this article helped me pinpoint which ones (all the entries in "Providers required by state" which had a - in the link. https://github.com/hashicorp/terraform/issues/27615
I corrected it by running the replace-provider command for each entry which was off, then running terraform init. I note doing this and running a git diff, the tfstate has been updated and now uses 0.14.x terraform instead of my previous 0.12.x. i.e.
terraform providers
terraform state replace-provider registry.terraform.io/-/azurerm registry.terraform.io/hashicorp/azurerm
Explanation: Your terraform project contains tf.state file that is outdated and refereeing to old provider address. The Error message will present this error:
Error: Invalid legacy provider address
This configuration or its associated state refers to the unqualified provider
<some-provider>.
You must complete the Terraform <some-version> upgrade process before upgrading to later
versions.
Solution: In order to solve this issue you should change the tf.state references to link to the newer required providers, update the tf.state file and initialize the project again. The steps are:
Create / Edit the required providers block with the relevant package name and version, I'd rather doing it on versions.tf file.
example:
terraform {
required_version = ">= 0.14"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 3.35.0"
}
}
}
Run terraform providers command to present the required providers from configuration against the required providers that saved on state.
example:
Providers required by configuration:
.
├── provider[registry.terraform.io/hashicorp/aws] >= 3.35.0
Providers required by state:
provider[registry.terraform.io/-/aws]
Switch and reassign the required provider source address in the terraform state ( using terraform state replace-provider command) so we can tell terraform how to interpret the legacy provider.
The terraform state replace-provider subcommand allows re-assigning
provider source addresses recorded in the Terraform state, and so we
can use this command to tell Terraform how to reinterpret the "legacy"
provider addresses as properly-namespaced providers that match with
the provider source addresses in the configuration.
Warning: The terraform state replace-provider subcommand, like all of
the terraform state subcommands, will create a new state snapshot and
write it to the configured backend. After the command succeeds the
latest state snapshot will use syntax that Terraform v0.12 cannot
understand, so you should perform this step only when you are ready to
permanently upgrade to Terraform v0.13.
example:
terraform state replace-provider registry.terraform.io/-/aws registry.terraform.io/hashicorp/aws
output:
~ Updating provider:
- registry.terraform.io/-/aws
+ registry.terraform.io/hashicorp/aws
run terraform init to update references.
While you were under TF13 did you apply state at least once for the running project?
According to TF docs: https://www.terraform.io/upgrade-guides/0-14.html
There is no automatic update command (separately) in 0.14 (like there was in 0.13). The only way to upgrade is to force state on a project at least once, while under command when moving TF13 to 14.
You can also try terraform init in the project directory.
my case was like this
Error: Invalid legacy provider address
This configuration or its associated state refers to the unqualified provider
"openstack".
You must complete the Terraform 0.13 upgrade process before upgrading to later
versions.
for resolving the issue
remove the .terraform folder
the execute the following command
terraform state replace-provider -- -/openstack terraform-provider-openstack/openstack
after this command, you will see the below print, enter yes
Terraform will perform the following actions:
~ Updating provider:
- registry.terraform.io/-/openstack
+ registry.terraform.io/terraform-provider-openstack/openstack
Changing 11 resources:
openstack_compute_servergroup_v2.kubernetes_master
openstack_networking_network_v2.kube_router
openstack_compute_instance_v2.kubernetes_worker
openstack_networking_subnet_v2.internal
openstack_networking_subnet_v2.kube_router
data.openstack_networking_network_v2.external_network
openstack_compute_instance_v2.kubernetes_etcd
openstack_networking_router_interface_v2.internal
openstack_networking_router_v2.internal
openstack_compute_instance_v2.kubernetes_master
openstack_networking_network_v2.internal
Do you want to make these changes?
Only 'yes' will be accepted to continue.
Enter a value: yes
Successfully replaced provider for 11 resources.
I recently ran into this using Terraform Cloud for the remote backend. We had some older AWS-related workspaces set to version 0.12.4 (in the cloud) that errored out with "Invalid legacy provider address" and refused to run with the latest Terraform client 1.1.8.
I am adding my answer because it is much simpler than the other answers. We did not do any of the following:
terraform providers
terraform 0.13upgrade
remove the .terraform folder
terraform state replace-provider
Instead we simply:
In a clean folder (no local state, using local terraform.exe version 0.13.7) ran 'terraform init'
Made a small insignificant change (to ensure apply would write state) to a .tf file in the workspace
In Terraform Cloud set the workspace version to 0.13.7
Using local 0.13.7 terraform.exe ran apply - that saved new state.
Now we can use cloud and local terraform.exe version 1.1.8 and no more problems.
Note that we did also need to update a few AWS S3-related resources to the newer AWS provider syntax to get all our workspaces working with the latest provider.
We encountered a similar problem in our operational environments today. We successfully completed the terraform 0.13upgrade command. This indeed introduced a versions.tf file.
However, performing a terraform init with this setup was still not possible, and the following error popped up:
Error: Invalid legacy provider address
Further investigation in the state file revealed that, for some resources, the provider block was not updated. We hence had to run the following command to finalize the upgrade process.
terraform state replace-provider "registry.terraform.io/-/google" "hashicorp/google"
EDIT Deployment to the next environment revealed that this was caused by conditional resources. To easily enable/disable some resources we leverage the count attribute and use either 0 or 1. For the resources with count = 0, that were unaltered with Terraform 0.13, the provider was not updated.
I was using terragrunt with remote s3 state and dynamo db and sadly this does not work for me. So posting it here might help someone else.
A long way to make this work, as terragrunt state replace-provider does work for me
download the state file from s3
aws s3 cp s3://bucket-name/path/terraform.tfstate terraform.tfstate --profile profile
replace the provider using terraform
terraform state replace-provider "registry.terraform.io/-/random" "hashicorp/random"
terraform state replace-provider "registry.terraform.io/-/aws" "hashicorp/aws"
upload the state file back to s3 as even terragrunt state push terraform.tfstate does not work for me
aws s3 cp terraform.tfstate s3://bucket-name/path/terraform.tfstate --profile profile
terragrunt apply
the command will throw error with digest value,
update the dynamo db table digest value that received in previous command
Initializing the backend...
Error refreshing state: state data in S3 does not have the expected content.
This may be caused by unusually long delays in S3 processing a previous state
update. Please wait for a minute or two and try again. If this problem
persists, and neither S3 nor DynamoDB are experiencing an outage, you may need
to manually verify the remote state and update the Digest value stored in the
DynamoDB table to the following value: fe2840edf8064d9225eea6c3ef2e5d1d
finally, run terragrunt apply
The other way that this can be strange is if you are using terraform workspaces - especially with the remote state files.
Using a terraform workspace - the order of operations is important.
terraform init - connecting to the default workspace
terraform workspace switch <env> - Even if you have specified the workspace here, the init will happen using the default workspace.
This is an assumption that terraform makes - sometimes erroneously
To fix this - you can run your init using:
TF_WORKSPACE=<your_env> terraform init
Or remove the default workspace.
I am starting to use Terraform and I have a .terraform folder created by "terraform init/apply" containing :
./plugins/linux_amd64/lock.json
./plugins/linux_amd64/terraform-provider-google
./plugins/modules/modules.json
terraform.tfstate
Should I version these files ? I would say no ...
The .terraform directory is a local cache where Terraform retains some files it will need for subsequent operations against this configuration. Its contents are not intended to be included in version control.
However, you can ensure that you can faithfully reproduce this directory on other systems by specifying certain things in your configuration that inform what Terraform will place in there:
Use required_providers in a terraform block to specify an exact version constraint for the Google Cloud Platform provider:
terraform {
required_providers {
google = "3.0.0"
}
}
(this relates to the .terraform/plugins directory)
In each module you call (which seems to be none so far, but perhaps in future), ensure its source refers to an exact version rather than to a floating branch (for VCS modules) or set version to an exact version (for modules from Terraform Registry):
module "example"
source = "git::https://github.com/example/example.git?ref=v2.0.0"
# ...
}
module "example"
source = "hashicorp/consul/aws"
version = "v1.2.0
}
(this relates to the .terraform/modules directory)
If you are using a remote backend, include the full configuration in the backend block inside the terraform block, rather than using the -backend-config argument to terraform init.
(this relates to the .terraform/terraform.tfstate file, which remembers your active backend configuration for later operations)