5851c31127
* terraform-providers: handle go modules More and more terraform providers are switching from vendored dependencies to Go modules. Let's say that you update the "aws" provider and it fails. You can run it again with: ./update-provider aws --vendor Any package that has the "vendorSha256" key will be considered as a go module package. The script now also supports adding new providers by using the <owner>/<repo> format. Eg: ./update-provider hetznercloud/hcloud --vendor * address comment Fixes https://github.com/NixOS/nixpkgs/pull/104667#discussion_r529788569 * support the null use-case * escape provider name as well * fix typo
178 lines
4.7 KiB
Bash
Executable file
178 lines
4.7 KiB
Bash
Executable file
#!/usr/bin/env nix-shell
|
|
#! nix-shell -i bash -p coreutils curl jq moreutils
|
|
# shellcheck shell=bash
|
|
# vim: ft=sh
|
|
#
|
|
# Update a terraform provider to the latest version advertised at the
|
|
# provider source address.
|
|
#
|
|
set -euo pipefail
|
|
|
|
show_usage() {
|
|
cat <<DOC
|
|
Usage: ./update-provider [--force] [--vendor] [<owner>/]<provider>
|
|
|
|
Update a single provider in the providers.json inventory file.
|
|
|
|
For example to update 'terraform-providers.aws' run:
|
|
|
|
./update-provider aws
|
|
|
|
If the provider is not in the list already, use the form '<owner>/<provider>'
|
|
to add the provider to the list:
|
|
|
|
./update-provider hetznercloud/hcloud
|
|
|
|
Options:
|
|
|
|
* --force: Force the update even if the version matches.
|
|
* --vendor: Switch from go package to go modules with vendor.
|
|
* --vendor-sha256 <sha256>: Override the SHA256 or "null".
|
|
DOC
|
|
}
|
|
|
|
force=
|
|
provider=
|
|
vendor=
|
|
vendorSha256=
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
-h | --help)
|
|
show_usage
|
|
exit
|
|
;;
|
|
--force)
|
|
force=1
|
|
shift
|
|
;;
|
|
--vendor)
|
|
force=1
|
|
vendor=1
|
|
shift
|
|
;;
|
|
--vendor-sha256)
|
|
force=1
|
|
vendorSha256=$2
|
|
shift 2
|
|
;;
|
|
*)
|
|
if [[ -n "$provider" ]]; then
|
|
echo "ERROR: provider name was passed two times: '$provider' and '$1'"
|
|
echo "Use --help for more info"
|
|
exit 1
|
|
fi
|
|
provider=$1
|
|
shift
|
|
esac
|
|
done
|
|
|
|
if [[ -z "$provider" ]]; then
|
|
echo "ERROR: No providers specified!"
|
|
echo
|
|
show_usage
|
|
exit 1
|
|
fi
|
|
|
|
provider_name=$(basename "$provider")
|
|
|
|
# Usage: read_attr <key>
|
|
read_attr() {
|
|
jq -r ".\"$provider_name\".\"$1\"" providers.json
|
|
}
|
|
|
|
# Usage: update_attr <key> <value>
|
|
update_attr() {
|
|
if [[ "$2" == "null" ]]; then
|
|
jq -S ".\"$provider_name\".\"$1\" = null" providers.json | sponge providers.json
|
|
else
|
|
jq -S ".\"$provider_name\".\"$1\" = \"$2\"" providers.json | sponge providers.json
|
|
fi
|
|
}
|
|
|
|
prefetch_github() {
|
|
# of a given owner, repo and rev, fetch the tarball and return the output of
|
|
# `nix-prefetch-url`
|
|
local owner=$1
|
|
local repo=$2
|
|
local rev=$3
|
|
nix-prefetch-url --unpack "https://github.com/$owner/$repo/archive/$rev.tar.gz"
|
|
}
|
|
|
|
old_source_address="$(read_attr provider-source-address)"
|
|
old_vendor_sha256=$(read_attr vendorSha256)
|
|
old_version=$(read_attr version)
|
|
|
|
if [[ $provider =~ ^[^/]+/[^/]+$ ]]; then
|
|
source_address=registry.terraform.io/$provider
|
|
else
|
|
source_address=$old_source_address
|
|
fi
|
|
if [[ "$source_address" == "null" ]]; then
|
|
echo "Could not find the source address for provider: $provider"
|
|
exit 1
|
|
fi
|
|
update_attr "provider-source-address" "$source_address"
|
|
|
|
# The provider source address (used inside Terraform `required_providers` block) is
|
|
# used to compute the registry API endpoint
|
|
#
|
|
# registry.terraform.io/hashicorp/aws (provider source address)
|
|
# registry.terraform.io/providers/hashicorp/aws (provider URL for the website)
|
|
# registry.terraform.io/v1/providers/hashicorp/aws (provider URL for the JSON API)
|
|
registry_response=$(curl -s https://"${source_address/\///v1/providers/}")
|
|
|
|
version="$(jq -r '.version' <<< "$registry_response")"
|
|
if [[ "$old_version" = "$version" && "$force" != 1 && -z "$vendorSha256" && "$old_vendor_sha256" != "$vendorSha256" ]]; then
|
|
echo "$provider_name is already at version $version"
|
|
exit
|
|
fi
|
|
update_attr version "$version"
|
|
|
|
provider_source_url="$(jq -r '.source' <<< "$registry_response")"
|
|
|
|
org="$(echo "$provider_source_url" | cut -d '/' -f 4)"
|
|
update_attr owner "$org"
|
|
repo="$(echo "$provider_source_url" | cut -d '/' -f 5)"
|
|
update_attr repo "$repo"
|
|
rev="$(jq -r '.tag' <<< "$registry_response")"
|
|
update_attr rev "$rev"
|
|
sha256=$(prefetch_github "$org" "$repo" "$rev")
|
|
update_attr sha256 "$sha256"
|
|
|
|
repo_root=$(git rev-parse --show-toplevel)
|
|
|
|
if [[ -z "$vendorSha256" ]]; then
|
|
if [[ "$old_vendor_sha256" == null ]]; then
|
|
vendorSha256=null
|
|
elif [[ -n "$old_vendor_sha256" || "$vendor" = 1 ]]; then
|
|
echo "=== Calculating vendorSha256 ==="
|
|
update_attr vendorSha256 "0000000000000000000000000000000000000000000000000000000000000000"
|
|
# Hackish way to find out the desired sha256. First build, then extract the
|
|
# error message from the logs.
|
|
set +e
|
|
nix-build --no-out-link "$repo_root" -A "terraform-providers.$provider_name.go-modules" 2>vendor_log.txt
|
|
set -e
|
|
logs=$(< vendor_log.txt)
|
|
if ! [[ $logs =~ got:\ +([^\ ]+) ]]; then
|
|
echo "ERROR: could not find new hash in output:"
|
|
cat vendor_log.txt
|
|
rm -f vendor_log.txt
|
|
exit 1
|
|
fi
|
|
rm -f vendor_log.txt
|
|
vendorSha256=${BASH_REMATCH[1]}
|
|
# Deal with nix unstable
|
|
if [[ $vendorSha256 = sha256-* ]]; then
|
|
vendorSha256=$(nix to-base32 "$vendorSha256")
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
if [[ -n "$vendorSha256" ]]; then
|
|
update_attr vendorSha256 "$vendorSha256"
|
|
fi
|
|
|
|
# Check that the provider builds
|
|
echo "=== Building terraform-providers.$provider_name ==="
|
|
nix-build "$repo_root" -A "terraform-providers.$provider_name"
|