aboutsummaryrefslogtreecommitdiff
path: root/infra/libkookie/nixpkgs/pkgs/applications/networking/cluster/terraform-providers/update-provider
blob: e1f1a0ef38a57d4bada7bf62b1424d988a434e8f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#!/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"