I use a CI system to compile terraform providers and bundle them into an image, but every time I run terraform init, I am getting the following error/failure.
│ Error: Failed to install provider
│
│ Error while installing rancher/rancher2 v1.13.0: the current package for
│ registry.terraform.io/rancher/rancher2 1.13.0 doesn't match any of the
│ checksums previously recorded in the dependency lock file
This message is repeated for all of the providers listed in my provider file, which looks like this:
terraform {
required_version = ">= 0.13"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "2.55.0"
}
github = {
source = "integrations/github"
version = "4.8.0"
}
}
...snip...
}
The terraform hcl lock file is stored in the repo and it's only when the lock file exists in the repo that these errors appear and terraform init fails. What could be the cause?
The dependency lock file is a file that belongs to the configuration as a whole, rather than to each separate module in the configuration. For that reason Terraform creates it and expects to find it in your current working directory when you run Terraform, which is also the directory containing the .
Manually unlock the state for the defined configuration. This will not modify your infrastructure. This command removes the lock on the state for the current configuration.
terraform. lock. hcl files should be committed in the same way as the one in the root of the project. In addition to this, we do regularly update the versions of the providers we want to use as we evaluate the changes.
While initializing your workspace, Terraform read the dependency lock file and downloaded the specified versions of the AWS and random providers. If Terraform did not find a lock file, it would download the latest versions of the providers that fulfill the version constraints you defined in the required_providers block.
Version constraints within the configuration itself determine which versions of dependencies are potentially compatible, but after selecting a specific version of each dependency Terraform remembers the decisions it made in a dependency lock file so that it can (by default) make the same decisions again in future.
To avoid this problem you can pre-populate checksums for a variety of different platforms in your lock file using the terraform providers lock command , which will then allow future calls to terraform init to verify that the packages available in your chosen mirror match the official packages from the provider's origin registry.
If you removed a provider dependency while using an earlier version of Terraform and then upgraded to Terraform v1.1 or later then you may see the error "missing or corrupted provider plugins", referring to the stale lock file entries.
The issue is that my local workstation is a Mac which uses the darwin platform, so all of the providers are downloaded for darwin and the hashes stored in the lockfile for that platform. When the CI system, which is running on Linux runs, it attempts to retrieve the providers listed in the lockfile, but the checksums don't match because they use a different platform.
The solution is to use the following command locally to generate a new terraform dependency lock file with all of the platforms for terraform, other systems running on different platforms will then be able to obey the dependency lock file.
terraform providers lock -platform=windows_amd64 -platform=darwin_amd64 -platform=linux_amd64
Just to improve a bit what was already posted above, I've done the same fix either in my local machine but also in automation (Github actions), wrapping up this solution into a tiny bash script. Putting this script into a GH action would solve this problem in a wider way
#!/usr/bin/env bash
export PATH=$PATH:/usr/local/bin
function main() {
parse_args "$@"
generate_terraform_lock_command_by_option
fix_lock_file
}
function fix_lock_file() {
pushd "$DIR" >/dev/null || exit
if [[ "${RUNON}" != "automation" ]]; then
clean_terraform_local_state
fi
if [[ -f ".terraform.lock.hcl" ]]; then
echo "Removing terraform.lock file"
cat $LOCK_FILE
rm -f "$LOCK_FILE"
fi
terraform get
terraform providers lock -platform=$OS
if [[ "${RUNON}" != "automation" ]]; then
clean_terraform_local_state
fi
popd >/dev/null || exit
}
function generate_terraform_lock_command_by_option(){
local platform
case "$PLATFORM" in
windows)
platform="windows_amd64"
;;
linux)
platform="darwin_amd64"
;;
mac)
platform="linux_amd64"
;;
*)
echo "Invalid platform: $PLATFORM"
exit 1
;;
esac
OS="$platform"
echo "Selected platform set: $OS"
}
function clean_terraform_local_state() {
if [[ -f ".terraform.tfstate" ]]; then
echo "Removing terraform.tfstate file"
rm terraform.tfstate
fi
if [[ -f ".terraform.tfstate.backup" ]]; then
echo "Removing terraform.tfstate.backup file"
rm terraform.tfstate.backup
fi
if [[ -d ".terraform" ]]; then
echo "Removing .terraform metadata folder to avoid local state conflicts "
rm -rf .terraform
fi
}
# Parse command line arguments
function parse_args() {
for arg in "$@"; do
echo "argument received --> [$arg]"
echo
done
for i in "$@"; do
case $i in
-d=* | --dir=*)
DIR="${i#*=}"
shift
;;
-=p* | --platform*)
PLATFORM="${i#*=}"
shift
;;
-e=* | --env=*)
ENV="${i#*=}"
shift
;;
-r=* | --runon=*)
RUNON="${i#*=}"
shift
;;
*) fatal "Unknown option: '-${i}'" "See '${0} --help' for usage" ;;
esac
done
}
# Globals
declare DIR
declare ENV
declare RUNON
declare LOCK_FILE=".terraform.lock.hcl"
declare OS
declare PLATFORM
[[ ${BASH_SOURCE[0]} != "$0" ]] || main "$@"
I'm running it from my local as follows:
.fix-terraform-lock-file.sh --dir=infrastructure/terraform/web_static --env=prod --platform=mac --runon=local
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With