Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 132 additions & 0 deletions .github/workflows/database-backup-dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
name: Database Backup

permissions:
contents: read

on:
workflow_call:
secrets:
CF_USER:
required: true
CF_PASSWORD:
required: true
CF_ORG:
required: true
PROJECT:
required: true
DATABASE_BACKUP_BASTION_NAME:
required: true

jobs:
startBastion:
name: Start Bastion
runs-on: ubuntu-latest
if: github.ref_protected == true
steps:
- name: Checkout
uses: actions/checkout@v6.0.2
- name: Set env
run: |
BRANCH=develop
CF_SPACE="dev"

echo "BRANCH=${BRANCH}" | tee -a $GITHUB_ENV
echo "CF_SPACE=${CF_SPACE}" | tee -a $GITHUB_ENV

- name: Install basic dependencies
run: ./scripts/pipeline/deb-basic-deps.sh
- name: Install Cloudfoundry CLI
run: ./scripts/pipeline/deb-cf-install.sh
- name: Cloud.gov login
env:
CF_USER: "${{ secrets.CF_USER }}"
CF_PASSWORD: "${{ secrets.CF_PASSWORD }}"
CF_ORG: "${{ secrets.CF_ORG }}"
PROJECT: "${{ secrets.PROJECT }}"
run: |
source ./scripts/pipeline/cloud-gov-login.sh
- name: Start Bastion
env:
PROJECT: "${{ secrets.PROJECT }}"
DATABASE_BACKUP_BASTION_NAME: "${{ secrets.DATABASE_BACKUP_BASTION_NAME }}"
run: |
cf start "${PROJECT}-${DATABASE_BACKUP_BASTION_NAME}-${CF_SPACE}" >/dev/null 2>&1
./scripts/pipeline/cloud-gov-wait-for-app-start.sh "${PROJECT}-${DATABASE_BACKUP_BASTION_NAME}-${CF_SPACE}"
backup-database:
runs-on: ubuntu-latest
continue-on-error: true
needs: startBastion
if: github.ref_protected == true
steps:
- name: Checkout
uses: actions/checkout@v6.0.2
- name: Set env
run: |
BRANCH=develop
CF_SPACE="dev"

echo "BRANCH=${BRANCH}" | tee -a $GITHUB_ENV
echo "CF_SPACE=${CF_SPACE}" | tee -a $GITHUB_ENV

- name: Install basic dependencies
run: ./scripts/pipeline/deb-basic-deps.sh
- name: Install AWSCLI
run: ./scripts/pipeline/deb-awscli.sh
- name: Install MySQL Client
run: ./scripts/pipeline/deb-mysql-client-install.sh
- name: Install Cloudfoundry CLI
run: ./scripts/pipeline/deb-cf-install.sh
- name: Cloud.gov login
env:
CF_USER: "${{ secrets.CF_USER }}"
CF_PASSWORD: "${{ secrets.CF_PASSWORD }}"
CF_ORG: "${{ secrets.CF_ORG }}"
PROJECT: "${{ secrets.PROJECT }}"
run: |
source ./scripts/pipeline/cloud-gov-login.sh
- name: Backup Database
id: backup
shell: bash
env:
CF_USER: "${{ secrets.CF_USER }}"
CF_PASSWORD: "${{ secrets.CF_PASSWORD }}"
CF_ORG: "${{ secrets.CF_ORG }}"
PROJECT: "${{ secrets.PROJECT }}"
DATABASE_BACKUP_BASTION_NAME: "${{ secrets.DATABASE_BACKUP_BASTION_NAME }}"
run: |
export TIMESTAMP=$(date --utc +%FT%TZ | tr ':', '-')
source ./scripts/pipeline/database-backup.sh
stopBastion:
name: Stop Bastion
runs-on: ubuntu-latest
needs: backup-database
if: github.ref_protected == true && ${{ always() }}
steps:
- name: Checkout
uses: actions/checkout@v6.0.2
- name: Set env
run: |
BRANCH=develop
CF_SPACE="dev"

echo "BRANCH=${BRANCH}" | tee -a $GITHUB_ENV
echo "CF_SPACE=${CF_SPACE}" | tee -a $GITHUB_ENV

- name: Install basic dependencies
run: ./scripts/pipeline/deb-basic-deps.sh
- name: Install Cloudfoundry CLI
run: ./scripts/pipeline/deb-cf-install.sh
- name: Cloud.gov login
env:
CF_USER: "${{ secrets.CF_USER }}"
CF_PASSWORD: "${{ secrets.CF_PASSWORD }}"
CF_ORG: "${{ secrets.CF_ORG }}"
PROJECT: "${{ secrets.PROJECT }}"
run: |
source ./scripts/pipeline/cloud-gov-login.sh
- name: Stop Bastion
env:
PROJECT: "${{ secrets.PROJECT }}"
DATABASE_BACKUP_BASTION_NAME: "${{ secrets.DATABASE_BACKUP_BASTION_NAME }}"
run: |
cf stop "${PROJECT}-${DATABASE_BACKUP_BASTION_NAME}-${CF_SPACE}" >/dev/null 2>&1
141 changes: 141 additions & 0 deletions .github/workflows/database-restore-dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
name: Database Restore

permissions:
contents: read

on:
workflow_dispatch:
inputs:
database_file_override:
description: "Path on S3 bucket to a specific database file to restore."
required: false
jobs:
start-bastion:
name: Start Bastion
runs-on: ubuntu-latest
if: ${{ always() }}
steps:
- name: Checkout
uses: actions/checkout@v6.0.2
- name: Set env.BRANCH
run: |
echo "BRANCH=$(echo $GITHUB_REF | cut -d'/' -f 3)" | tee -a $GITHUB_ENV
case ${BRANCH} in
develop)
CF_SPACE="dev"
;;
main)
CF_SPACE="prod"
;;
stage)
CF_SPACE="staging"
;;
esac
echo "CF_SPACE=${CF_SPACE}" | tee -a $GITHUB_ENV
- name: Install basic dependancies
run: ./scripts/pipeline/deb-basic-deps.sh
- name: Install Cloudfoundry CLI
run: ./scripts/pipeline/deb-cf-install.sh
- name: Cloud.gov login
env:
CF_USER: "${{ secrets.CF_USER }}"
CF_PASSWORD: "${{ secrets.CF_PASSWORD }}"
CF_ORG: "${{ secrets.CF_ORG }}"
PROJECT: "${{ secrets.PROJECT }}"
run: source ./scripts/pipeline/cloud-gov-login.sh
- name: Start Bastion
env:
DATABASE_BACKUP_BASTION_NAME: "${{ secrets.DATABASE_BACKUP_BASTION_NAME }}"
PROJECT: "${{ secrets.PROJECT }}"
run: |
cf start "${PROJECT}-${DATABASE_BACKUP_BASTION_NAME}-${CF_SPACE}" >/dev/null 2>&1
./scripts/pipeline/cloud-gov-wait-for-app-start.sh "${PROJECT}-${DATABASE_BACKUP_BASTION_NAME}-${CF_SPACE}"
restore-database:
runs-on: ubuntu-latest
needs: start-bastion
steps:
- name: Checkout
uses: actions/checkout@v6.0.2
- name: Set env.BRANCH
run: |
echo "BRANCH=$(echo $GITHUB_REF | cut -d'/' -f 3)" | tee -a $GITHUB_ENV

case ${BRANCH} in
develop)
CF_SPACE="dev"
;;
main)
CF_SPACE="prod"
;;
stage)
CF_SPACE="staging"
;;
esac
echo "CF_SPACE=${CF_SPACE}" | tee -a $GITHUB_ENV
- name: Install basic dependancies
run: ./scripts/pipeline/deb-basic-deps.sh
- name: Install AWSCLI
run: ./scripts/pipeline/awscli-install.sh
- name: Install MySQL Client
run: ./scripts/pipeline/deb-mysql-client-install.sh
- name: Install Cloudfoundry CLI
run: ./scripts/pipeline/deb-cf-install.sh
- name: Cloud.gov login
env:
CF_USER: "${{ secrets.CF_USER }}"
CF_PASSWORD: "${{ secrets.CF_PASSWORD }}"
CF_ORG: "${{ secrets.CF_ORG }}"
PROJECT: "${{ secrets.PROJECT }}"
run: source ./scripts/pipeline/cloud-gov-login.sh
- name: Restore database
shell: bash
env:
CF_USER: "${{ secrets.CF_USER }}"
CF_PASSWORD: "${{ secrets.CF_PASSWORD }}"
CF_ORG: "${{ secrets.CF_ORG }}"
PROJECT: "${{ secrets.PROJECT }}"
DATABASE_BACKUP_BASTION_NAME: "${{ secrets.DATABASE_BACKUP_BASTION_NAME }}"
run: |
export S3_FILE_PATH=${{ github.event.inputs.database_file_override }}
source ./scripts/pipeline/s3-backup-download.sh
source ./scripts/pipeline/database-restore.sh
source ./scripts/pipeline/cloud-gov-post-deploy.sh
stop-bastion:
name: Stop Bastion
runs-on: ubuntu-latest
needs: restore-database
if: ${{ always() }}
steps:
- name: Checkout
uses: actions/checkout@v6.0.2
- name: Set env.BRANCH
run: |
echo "BRANCH=$(echo $GITHUB_REF | cut -d'/' -f 3)" | tee -a $GITHUB_ENV
case ${BRANCH} in
develop)
CF_SPACE="dev"
;;
main)
CF_SPACE="prod"
;;
stage)
CF_SPACE="staging"
;;
esac
echo "CF_SPACE=${CF_SPACE}" | tee -a $GITHUB_ENV
- name: Install basic dependancies
run: ./scripts/pipeline/deb-basic-deps.sh
- name: Install Cloudfoundry CLI
run: ./scripts/pipeline/deb-cf-install.sh
- name: Cloud.gov login
env:
CF_USER: "${{ secrets.CF_USER }}"
CF_PASSWORD: "${{ secrets.CF_PASSWORD }}"
CF_ORG: "${{ secrets.CF_ORG }}"
PROJECT: "${{ secrets.PROJECT }}"
run: source ./scripts/pipeline/cloud-gov-login.sh
- name: Stop Bastion
env:
DATABASE_BACKUP_BASTION_NAME: "${{ secrets.DATABASE_BACKUP_BASTION_NAME }}"
PROJECT: "${{ secrets.PROJECT }}"
run: cf stop "${PROJECT}-${DATABASE_BACKUP_BASTION_NAME}-${CF_SPACE}" >/dev/null 2>&1
27 changes: 17 additions & 10 deletions scripts/cloud-gov-s3-creds.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,19 @@
## Get current username with no special characters.
user=$(whoami | tr -dc '[:alnum:]\n\r' | tr '[:upper:]' '[:lower:]')

if [ -z "${bucket_name}" ]; then
echo -e "Error: No bucket name is set!\n"
echo -e "Export the bucket name, found with 'cf services | grep s3', then run the script again."
echo -e "This is the name of the bucket in cloud.gov, not the AWS bucket name.\n"
echo -e "Example usage:\n\texport bucket_name=project-bucket-name-environment\n\t$0\n"
return
## Find the CF s3 service name. Look on the command line, then in the environment.
cf_service=$1
if [ -z "${cf_service}" ]; then
cf_service="${cf_s3_service}"
if [ -z "${cf_service}" ]; then
echo -e "Error: No CF s3 service name is set!\n"
echo -e "Export the CF s3 service name, found with 'cf services | grep s3', then run the script again."
echo -e "This is the name of the bucket in cloud.gov, not the AWS CF s3 service name.\n"
echo -e "Example usage:\n\texport cf_service=project-bucket-name-environment\n\t$0\n"
return
fi
else
shift
fi

if [ -n "$(cf orgs | grep FAILED)" ]; then
Expand All @@ -17,18 +24,18 @@ fi

echo "Deleting old credentials..."
{
service_key="${bucket_name}-${user}-key"
service_key="${cf_service}-${user}-key"

## Delete any old keys.
cf delete-service-key "${bucket_name}" "${service_key}" -f
cf delete-service-key "${cf_service}" "${service_key}" -f
} >/dev/null 2>&1

[ "${1}" = "-d" ] && echo "AWS bucket key deleted." && return

echo "Creating key..."
{
cf create-service-key "${bucket_name}" "${service_key}"
s3_credentials=$(cf service-key "${bucket_name}" "${service_key}" | tail -n +2)
cf create-service-key "${cf_service}" "${service_key}"
s3_credentials=$(cf service-key "${cf_service}" "${service_key}" | tail -n +2)
aws_access_key=$(echo "${s3_credentials}" | jq -r '.credentials.access_key_id')
aws_bucket_name=$(echo "${s3_credentials}" | jq -r '.credentials.bucket')
aws_bucket_region=$(echo "${s3_credentials}" | jq -r '.credentials.region')
Expand Down
44 changes: 16 additions & 28 deletions scripts/download_backup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ fi
help(){
echo "Usage: $0 [options]" >&2
echo
echo " -b The name of the S3 bucket with the backup."
echo " -e Environment of backup to download."
echo " -c The name of the CF service containing the S3 bucket with the backup."
echo " -s Name of the space the backup bucket is in."
echo " -d Date to retrieve backup from. Acceptable values
are 'latest' or in 'YYYY-MM-DD' format and no
Expand All @@ -69,45 +68,34 @@ help(){
RED='\033[0;31m'
NC='\033[0m'

while getopts 'b:e:s:d:' flag; do
while getopts 'c:e:s:d:' flag; do
case ${flag} in
b) backup_bucket=${OPTARG} ;;
e) env=${OPTARG} ;;
c) cf_s3_service=${OPTARG} ;;
s) space=${OPTARG} ;;
d) retrieve_date=${OPTARG} ;;
*) help && exit 1 ;;
esac
done

[[ -z "${backup_bucket}" ]] && help && echo -e "\n${RED}Error: Missing -b flag.${NC}" && exit 1
[[ -z "${env}" ]] && help && echo -e "\n${RED}Error: Missing -e flag.${NC}" && exit 1
[[ -z "${cf_s3_service}" ]] && help && echo -e "\n${RED}Error: Missing -b flag.${NC}" && exit 1
[[ -z "${space}" ]] && help && echo -e "\n${RED}Error: Missing -s flag.${NC}" && exit 1
[[ -z "${retrieve_date}" ]] && help && echo -e "\n${RED}Error: Missing -d flag.${NC}" && exit 1

echo "Getting backup bucket credentials..."
echo "Getting backup bucket credentials for $cf_s3_service in $space ..."
{
cf target -s "${space}"
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
. "${script_dir}/cloud-gov-s3-creds.sh" ${cf_s3_service}
export bucket="${AWS_BUCKET}"
} &>/dev/null
[ $? -ne 0 ] && echo -e "\n${RED}Error: Failed to get backup bucket credentials.${NC}" && exit 1

export service="${backup_bucket}"
export service_key="${service}-key"
cf delete-service-key "${service}" "${service_key}" -f
cf create-service-key "${service}" "${service_key}"
sleep 2
export s3_credentials=$(cf service-key "${service}" "${service_key}" | tail -n +2)

export AWS_ACCESS_KEY_ID=$(echo "${s3_credentials}" | jq -r '.credentials.access_key_id')
export bucket=$(echo "${s3_credentials}" | jq -r '.credentials.bucket')
export AWS_DEFAULT_REGION=$(echo "${s3_credentials}" | jq -r '.credentials.region')
export AWS_SECRET_ACCESS_KEY=$(echo "${s3_credentials}" | jq -r '.credentials.secret_access_key')

} >/dev/null 2>&1

echo "Downloading backup..."
echo "Downloading backup from $bucket..."
{

aws s3 cp s3://${bucket}/${env}/${retrieve_date}.tar.gz . --no-verify-ssl 2>/dev/null
cf delete-service-key "${service}" "${service_key}" -f

} >/dev/null 2>&1
aws s3 cp s3://${bucket}/${retrieve_date}.sql.gz . --no-verify-ssl
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
. "${script_dir}/cloud-gov-s3-creds.sh" -d
} &>/dev/null
[ $? -ne 0 ] && echo -e "\n${RED}Error: Failed to download backup from S3 bucket.${NC}" && exit 1

echo "File saved: ${retrieve_date}.tar.gz"
Loading