Skip to content

Instantly share code, notes, and snippets.

@hongkongkiwi
Last active November 16, 2023 23:38
Show Gist options
  • Select an option

  • Save hongkongkiwi/6198cc254f4bb0ef8df33a9850ac7bc0 to your computer and use it in GitHub Desktop.

Select an option

Save hongkongkiwi/6198cc254f4bb0ef8df33a9850ac7bc0 to your computer and use it in GitHub Desktop.
Initialises Terraform HTTP backend to Gitlab. Here's a nice script which will ask for details in an interactive way.
# More information can be found at https://docs.gitlab.com/ee/user/infrastructure/#gitlab-managed-terraform-state
terraform {
backend "http" {
}
}
#!/bin/bash
check_password() {
security find-generic-password \
-s "$1" > /dev/null 2>&1 && return 0 || return 1
}
get_username() {
[ -z "$1" ] && { echo >&2 "get_password(): Service name required1"; return 1; }
check_password "$1" || { echo >&2 "get_password(): No password found!"; return 1; }
security find-generic-password \
-D "application password" -s "$1" -g 2>&1 | grep "\"acct\"<blob>=" | cut -d '=' -f2 | cut -d '"' -f2
}
get_password() {
[ -z "$1" ] && { echo >&2 "get_password(): Service name required1"; return 1; }
check_password "$1" || { echo >&2 "get_password(): No password found!"; return 1; }
security find-generic-password \
-D "application password" -s "$1" -g 2>&1 | grep "password: " | cut -d '"' -f2
}
set_password() {
[ -z "$1" ] && { echo >&2 "set_password(): Service name required1"; return 1; }
[ -z "$2" ] && { echo >&2 "set_password(): Username required1"; return 1; }
[ -z "$3" ] && { echo >&2 "set_password(): Password required1"; return 1; }
security add-generic-password \
-s "$1" \
-a "$2" \
-w "$3" \
-j "Gitlab Terraform Setup Script Access token" \
-D "application password" \
-U
}
ask_user_details() {
while read -p "Gitlab Username [$INPUT_TF_USERNAME]: " TF_USERNAME; do
if [ -z "$INPUT_TF_USERNAME" ] && [ -z "$TF_USERNAME" ]; then
echo "ERROR: gitlab Username cannot be empty!"
continue
elif [ -z $INPUT_TF_USERNAME ] && [ ! -z $TF_USERNAME ]; then
INPUT_TF_USERNAME="$TF_USERNAME"
break
elif [ ! -z $INPUT_TF_USERNAME ] && [ -z $TF_USERNAME ]; then
TF_USERNAME="$INPUT_TF_USERNAME"
break
elif [ ! -z $INPUT_TF_USERNAME ] && [ ! -z $TF_USERNAME ]; then
INPUT_TF_USERNAME="$TF_USERNAME"
break
fi
done
while read -p "Access Token [$INPUT_TF_ACCESS_TOKEN]: " TF_ACCESS_TOKEN; do
if [ -z "$INPUT_TF_ACCESS_TOKEN" ] && [ -z "$TF_ACCESS_TOKEN" ]; then
echo "ERROR: Access Token cannot be empty!"
continue
elif [ -z $INPUT_TF_ACCESS_TOKEN ] && [ ! -z $TF_ACCESS_TOKEN ]; then
INPUT_TF_ACCESS_TOKEN="$TF_ACCESS_TOKEN"
break
elif [ ! -z $INPUT_TF_ACCESS_TOKEN ] && [ -z $TF_ACCESS_TOKEN ]; then
TF_ACCESS_TOKEN="$INPUT_TF_ACCESS_TOKEN"
break
elif [ ! -z $INPUT_TF_ACCESS_TOKEN ] && [ ! -z $TF_ACCESS_TOKEN ]; then
INPUT_TF_ACCESS_TOKEN="$TF_ACCESS_TOKEN"
break
fi
done
while read -p "Project ID [$INPUT_PROJECT_ID]: " TF_PROJECT_ID; do
if [ -z "$INPUT_PROJECT_ID" ] && [ -z "$TF_PROJECT_ID" ]; then
echo "ERROR: Project ID cannot be empty!"
continue
else
if [[ ! $TF_PROJECT_ID =~ ^[0-9]+$ ]] && [[ ! $INPUT_PROJECT_ID =~ ^[0-9]+$ ]]; then
echo "ERROR: Project ID can only contain digits!"
continue
elif [ -z $INPUT_PROJECT_ID ] && [ ! -z $TF_PROJECT_ID ]; then
INPUT_PROJECT_ID="$TF_PROJECT_ID"
break
elif [ ! -z $INPUT_PROJECT_ID ] && [ -z $TF_PROJECT_ID ]; then
TF_PROJECT_ID="$INPUT_PROJECT_ID"
break
elif [ ! -z $INPUT_PROJECT_ID ] && [ ! -z $TF_PROJECT_ID ]; then
INPUT_PROJECT_ID="$TF_PROJECT_ID"
break
fi
fi
done
}
ask_state_name() {
while read -p "Terraform State Name [$INPUT_TF_STATE_NAME]: " TF_STATE_NAME; do
if [ -z "$INPUT_TF_STATE_NAME" ] && [ -z "$TF_STATE_NAME" ]; then
echo "ERROR: State name cannot be empty!"
continue
elif [ -z $INPUT_TF_STATE_NAME ] && [ ! -z $TF_STATE_NAME ]; then
INPUT_TF_STATE_NAME="$TF_STATE_NAME"
break
elif [ ! -z $INPUT_TF_STATE_NAME ] && [ -z $TF_STATE_NAME ]; then
TF_STATE_NAME="$INPUT_TF_STATE_NAME"
break
elif [ ! -z $INPUT_TF_ACCESS_TOKEN ] && [ ! -z $TF_STATE_NAME ]; then
INPUT_TF_STATE_NAME="$TF_STATE_NAME"
break
fi
done
}
check_access_token() {
request_cmd="$(curl -i -o - --silent -X GET --header "Accept: application/json" --header "PRIVATE-TOKEN: $1" "https://gitlab.com/api/v4/projects")"
http_status=$(echo "$request_cmd" | grep HTTP | awk '{print $2}')
if [ $http_status -ge 200 ] && [ $http_status -le 299 ]; then
return 0
else
return $http_status
fi
}
get_project_details() {
HTTP_RESPONSE="$(curl --write-out "\nHTTPSTATUS:%{http_code}" --silent -X GET --header "Accept: application/json" --header "PRIVATE-TOKEN: $1" "https://gitlab.com/api/v4/projects/$2")"
HTTP_STATUS=$(echo $HTTP_RESPONSE | tr -d '\n' | sed -e 's/.*HTTPSTATUS://')
if [ $HTTP_STATUS -ge 200 ] && [ $HTTP_STATUS -le 299 ]; then
echo "$HTTP_RESPONSE" | sed -e 's/^HTTPSTATUS\:.*//g'
return 0
else
return $HTTP_STATUS
fi
}
INPUT_TF_USERNAME="${GITLAB_USERNAME:-"$1"}"
INPUT_TF_ACCESS_TOKEN="${GITLAB_ACCESS_TOKEN:-"$2"}"
INPUT_PROJECT_ID="$3"
INPUT_TF_STATE_NAME="$4"
if [ -z "$INPUT_TF_ACCESS_TOKEN" ]; then
if check_password "gitlab"; then
INPUT_TF_ACCESS_TOKEN=`get_password "gitlab"`
SAVED_TF_ACCESS_TOKEN="$INPUT_TF_ACCESS_TOKEN"
fi
fi
if [ -z "$INPUT_TF_USERNAME" ]; then
if check_password "gitlab"; then
INPUT_TF_USERNAME=`get_username "gitlab"`
SAVED_TF_USERNAME="$INPUT_TF_USERNAME"
fi
fi
DETAILS_CORRECT=""
PROJECT_DETAILS=""
while true; do
ask_user_details
check_access_token "$TF_ACCESS_TOKEN" || { echo >&2 "ERROR: Invalid Access Token"; continue; }
PROJECT_DETAILS=`get_project_details "$TF_ACCESS_TOKEN" "$TF_PROJECT_ID"` || { echo >&2 "ERROR: Invalid Project ID"; continue; }
[ -z $INPUT_TF_STATE_NAME ] && INPUT_TF_STATE_NAME="`echo "$PROJECT_DETAILS" | jq -r '.name'`-dev"
ask_state_name
read -p "Are these details correct? [Yn]: " -n 1 -r DETAILS_CORRECT
[ -z $DETAILS_CORRECT ] && DETAILS_CORRECT="y"
if [[ $DETAILS_CORRECT =~ ^[Yy]$ ]]; then
printf "\n"
break
else
printf "\n"
fi
done
if [[ ( "$SAVED_TF_USERNAME" != "$TF_USERNAME" && -z "$GITLAB_USERNAME" ) ||
( "$SAVED_TF_ACCESS_TOKEN" != "$TF_ACCESS_TOKEN" && -z "$GITLAB_ACCESS_TOKEN" ) ]]; then
read -p "Saved Gitlab Username or Access Token has changed. Update keychain? [Y]: " -n 1 -r ANSWER
if [[ ! $ANSWER =~ ^[Nn]$ ]]; then
set_password "gitlab" "$TF_USERNAME" "$TF_ACCESS_TOKEN"
fi
echo ""
fi
TF_ADDRESS="https://gitlab.com/api/v4/projects/${TF_PROJECT_ID}/terraform/state/${TF_STATE_NAME}"
echo "Now initailising repo..."
[ -d "$PWD/.terraform" ] && rm -Rf "$PWD/.terraform"
echo terraform init \
-backend-config="address=${TF_ADDRESS}" \
-backend-config="lock_address=${TF_ADDRESS}/lock" \
-backend-config="unlock_address=${TF_ADDRESS}/lock" \
-backend-config="username=${TF_USERNAME}" \
-backend-config="password=${TF_ACCESS_TOKEN}" \
-backend-config="lock_method=POST" \
-backend-config="unlock_method=DELETE" \
-backend-config="retry_wait_min=5"
@spham
Copy link
Copy Markdown

spham commented Nov 16, 2023

thank you very much

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment