Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Terraform: Failed to install provider, doesn't match checksums from dependency lock file

Tags:

terraform

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?

like image 909
Highway of Life Avatar asked Apr 21 '21 23:04

Highway of Life


People also ask

What is dependency lock file in Terraform?

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 .

How do I remove Terraform lock?

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.

Should I commit Terraform lock HCL?

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.

How does terraform read the dependency lock file?

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.

How does terraform decide which versions of dependencies are compatible?

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.

How can I prevent terraform init from failing to detect packages?

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.

Why are my provider plugins not working in TerraForm?

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.


2 Answers

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
like image 113
Highway of Life Avatar answered Oct 19 '22 20:10

Highway of Life


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
like image 21
Alex Torres Avatar answered Oct 19 '22 20:10

Alex Torres