Skip to content

Instantly share code, notes, and snippets.

@fprimex
Last active June 18, 2021 19:07
Show Gist options
  • Save fprimex/1c8e7a03e811ee52441053ce6f8983e0 to your computer and use it in GitHub Desktop.
Save fprimex/1c8e7a03e811ee52441053ce6f8983e0 to your computer and use it in GitHub Desktop.
Push a state to TFC / TFE using the API
#!/bin/sh
e=
tfe_workspace_id="$1"
state_file="$2"
if [ -z "$tfe_workspace_id" ]; then
echo "workspace ID is required"
e=1
fi
if [ ! -f "$state_file" ]; then
echo "file not found: $state_file"
e=1
fi
if [ -z "$TFE_TOKEN" ]; then
echo "TFE_TOKEN env var needs to be set"
e=1
fi
if [ -z "$TFE_HOSTNAME" ]; then
echo "TFE_HOSTNAME env var needs to be set"
e=1
fi
if [ -n "$e" ]; then
exit 1
fi
payload () {
cat << EOF
{
"data": {
"type":"state-versions",
"attributes": {
"serial": $1,
"md5": "$2",
"lineage": "$3",
"state": "$4"
}
}
}
EOF
}
handle_resp () {
resp_body="$(printf '%s' "$1" | awk '!/^http_code/; /^http_code/{next}')"
resp_code="$(printf '%s' "$1" | awk '!/^http_code/{next} /^http_code/{print $2}')"
case "$resp_code" in
2*)
echo "$resp_code"
;;
4*|5*)
echo "$resp_code"
echo "$resp_body"
exit 1
;;
*)
echo "unknown response"
echo "$resp_code"
echo "$resp_body"
exit 1
;;
esac
}
os="$(uname -s)"
serial="$(jq -r '.serial' "$state_file")"
serial="$(( $serial + 10 ))"
jq -r --arg serial "$serial" '.serial = ($serial | tonumber) | .' "$state_file" > "${state_file}_updated"
state_file="${state_file}_updated"
if [ "$os" = "Darwin" ]; then
md5="$(md5 -q "$state_file")"
else
md5="$(md5sum "$state_file" | cut -d ' ' -f 1)"
fi
lineage="$(jq -r '.lineage' "$state_file")"
if [ "$os" = "Darwin" ]; then
b64="$(base64 "$state_file")"
else
b64="$(base64 -w 0 "$state_file")"
fi
payload "$serial" "$md5" "$lineage" "$b64" > payload.json
echo "uploading $state_file to $tfe_workspace_id"
echo " preemptive unlock"
resp="$(curl \
-w '\nhttp_code: %{http_code}\n' \
--header "Authorization: Bearer $TFE_TOKEN" \
--header "Content-Type: application/vnd.api+json" \
--request POST \
--data '{"reason":"state update"}' \
-s \
"https://$TFE_HOSTNAME/api/v2/workspaces/$tfe_workspace_id/actions/unlock" >/dev/null 2>&1)"
printf " locking: "
resp="$(curl \
-w '\nhttp_code: %{http_code}\n' \
--header "Authorization: Bearer $TFE_TOKEN" \
--header "Content-Type: application/vnd.api+json" \
--request POST \
--data '{"reason":"state update"}' \
-s \
"https://$TFE_HOSTNAME/api/v2/workspaces/$tfe_workspace_id/actions/lock")"
handle_resp "$resp"
printf " uploading: "
resp="$(curl \
-w '\nhttp_code: %{http_code}\n' \
--header "Authorization: Bearer $TFE_TOKEN" \
--header "Content-Type: application/vnd.api+json" \
--request POST \
--data @payload.json \
-s \
"https://$TFE_HOSTNAME/api/v2/workspaces/$tfe_workspace_id/state-versions")"
handle_resp "$resp"
printf " unlocking: "
resp="$(curl \
-w '\nhttp_code: %{http_code}\n' \
--header "Authorization: Bearer $TFE_TOKEN" \
--header "Content-Type: application/vnd.api+json" \
--request POST \
--data '{"reason":"state update"}' \
-s \
"https://$TFE_HOSTNAME/api/v2/workspaces/$tfe_workspace_id/actions/unlock")"
handle_resp "$resp"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment