Skip to content

Commit

Permalink
feat!: crunchy - default (#2133)
Browse files Browse the repository at this point in the history
Signed-off-by: OMPRAKASH MISHRA <[email protected]>
Co-authored-by: Derek Roberts <[email protected]>
  • Loading branch information
mishraomp and DerekRoberts authored Oct 25, 2024
1 parent ab017c2 commit 58e34f3
Show file tree
Hide file tree
Showing 17 changed files with 978 additions and 185 deletions.
134 changes: 134 additions & 0 deletions .github/workflows/.dbdeployer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
name: .Database Deploy

on:
workflow_call:
inputs: ### Required
directory:
description: Crunchy Chart directory
default: 'charts/crunchy'
required: false
type: string
oc_server:
default: https://api.silver.devops.gov.bc.ca:6443
description: 'OpenShift server'
required: false
type: string
environment:
description: Environment name; omit for PRs
required: false
type: string
s3_enabled:
description: Enable S3 backups
required: false
type: boolean
secrets:
oc_namespace:
description: OpenShift namespace
required: true
oc_token:
description: OpenShift token
required: true
s3_access_key:
description: S3 access key
required: false
s3_secret_key:
description: S3 secret key
required: false
s3_bucket:
description: S3 bucket
required: false
s3_endpoint:
description: S3 endpoint
required: false
jobs:
deploy_db:
runs-on: ubuntu-24.04
name: Deploy Crunchy DB If not Deployed
environment: ${{ inputs.environment }}
steps:
- uses: actions/checkout@v4
- name: Install CLI tools from OpenShift Mirror
uses: redhat-actions/openshift-tools-installer@v1
with:
oc: "4.14.37"
- name: Validate Inputs
shell: bash
run: |
if [ ${{ inputs.s3_enabled }} == true ]; then
echo "S3 ie enabled for backups, checking for mandatory secrets"
if [ ! "${{ secrets.s3_access_key }}" ]; then
echo "S3 access key not found"
exit 1
fi
if [ ! "${{ secrets.s3_secret_key }}" ]; then
echo "S3 secret key not found"
exit 1
fi
if [ ! "${{ secrets.s3_bucket }}" ]; then
echo "S3 bucket not found"
exit 1
fi
if [ ! "${{ secrets.s3_endpoint }}" ]; then
echo "S3 endpoint not found"
exit 1
fi
fi
- name: OC Login
shell: bash
run: |
# OC Login
OC_TEMP_TOKEN=$(curl -k -X POST ${{ inputs.oc_server }}/api/v1/namespaces/${{ secrets.oc_namespace }}/serviceaccounts/pipeline/token --header "Authorization: Bearer ${{ secrets.oc_token }}" -d '{"spec": {"expirationSeconds": 600}}' -H 'Content-Type: application/json; charset=utf-8' | jq -r '.status.token' )
oc login --token=$OC_TEMP_TOKEN --server=${{ inputs.oc_server }}
oc project ${{ secrets.oc_namespace }} # Safeguard!
- name: Deploy Database
working-directory: ${{ inputs.directory }}
shell: bash
run: |
echo 'Deploying crunchy helm chart'
if [ ${{ secrets.s3_endpoint }} ]; then
helm status postgres || \
helm upgrade --install --wait --set crunchy.pgBackRest.s3.enabled=true \
--set-string crunchy.pgBackRest.s3.accessKey=${{ secrets.s3_access_key }} \
--set-string crunchy.pgBackRest.s3.secretKey=${{ secrets.s3_secret_key }} \
--set-string crunchy.pgBackRest.s3.bucket=${{ secrets.s3_bucket }} \
--set-string crunchy.pgBackRest.s3.endpoint=${{ secrets.s3_endpoint }} \
postgres .
else
helm status postgres || \
helm upgrade --install --wait postgres .
fi
- name: Add PR specific user to Crunchy DB # only for PRs
shell: bash
if: github.event.inputs.environment == ''
run: |
echo 'Adding PR specific user to Crunchy DB'
NEW_USER='{"databases":["app-${{ github.event.number }}"],"name":"app-${{ github.event.number }}"}'
CURRENT_USERS=$(oc get PostgresCluster/postgres-crunchy -o json | jq '.spec.users')
echo "${CURRENT_USERS}"
# check if current_users already contains the new_user
if echo "${CURRENT_USERS}" | jq -e ".[] | select(.name == \"app-${{ github.event.number }}\")" > /dev/null; then
echo "User already exists"
exit 0
fi
UPDATED_USERS=$(echo "${CURRENT_USERS}" | jq --argjson NEW_USER "${NEW_USER}" '. + [$NEW_USER]')
PATCH_JSON=$(jq -n --argjson users "${UPDATED_USERS}" '{"spec": {"users": $users}}')
oc patch PostgresCluster/postgres-crunchy --type=merge -p "${PATCH_JSON}"
# wait for sometime as it takes time to create the user, query the secret and check if it is created, otherwise wait in a loop for 5 rounds
for i in {1..5}; do
if oc get secret postgres-crunchy-pguser-app-${{ github.event.number }} -o jsonpath='{.metadata.name}' > /dev/null; then
echo "Secret created"
break
else
echo "Secret not created, waiting for 60 seconds"
sleep 60
fi
done
195 changes: 195 additions & 0 deletions .github/workflows/.deployer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
name: .Helm Deployer

on:
workflow_call:
inputs:
### Required
# Only secrets!

### Typical / recommended
atomic:
description: Atomic deployment? That means fail all or nothing
default: true
required: false
type: string
directory:
description: Chart directory
default: 'charts/app'
required: false
type: string
environment:
description: Environment name; omit for PRs
required: false
type: string
oc_server:
default: https://api.silver.devops.gov.bc.ca:6443
description: 'OpenShift server'
required: false
type: string
params:
description: 'Extra parameters to pass to helm upgrade'
default: ''
required: false
type: string
tag:
description: Specify a tag to deploy; defaults to PR number
required: false
type: string
triggers:
description: Paths used to trigger a deployment; e.g. ('./backend/' './frontend/)
required: false
type: string
db_user:
description: The database user
required: false
type: string

### Usually a bad idea / not recommended
timeout-minutes:
description: 'Timeout minutes'
default: 10
required: false
type: number
values:
description: 'Values file'
default: 'values.yaml'
required: false
type: string

outputs:
triggered:
description: 'Has a deployment has been triggered?'
value: ${{ jobs.deployer.outputs.triggered }}

secrets:
oc_namespace:
description: OpenShift namespace
required: true
oc_token:
description: OpenShift token
required: true

jobs:
deployer:
name: Helm
environment: ${{ inputs.environment }}
runs-on: ubuntu-24.04
outputs:
triggered: ${{ steps.triggers.outputs.triggered }}
steps:
### Triggers, tag and release

# Check triggers (omitted or matched) for deployment
- uses: bcgov-nr/[email protected]
id: triggers
with:
triggers: ${{ inputs.triggers }}

# Variables
- if: ${{ steps.triggers.outputs.triggered == 'true' && inputs.tag == '' }}
id: pr
uses: bcgov-nr/[email protected]
- if: steps.triggers.outputs.triggered == 'true'
id: vars
run: |
# Vars: tag and release
# Tag defaults to PR number, but can be overridden by inputs.tag
tag=${{ inputs.tag || steps.pr.outputs.pr }}
# Release name includes run numbers to ensure uniqueness
release=${{ github.event.repository.name }}-${{ inputs.environment || steps.pr.outputs.pr || inputs.tag }}
# version, to support helm packaging for non-pr based releases (workflow_dispatch). default to 1.0.0+github run number
version=1.0.0+${{ github.run_number }}
# Summary
echo "tag=${tag}"
echo "release=${release}"
echo "version=${version}"
# Output
echo "tag=${tag}" >> $GITHUB_OUTPUT
echo "release=${release}" >> $GITHUB_OUTPUT
echo "version=${version}" >> $GITHUB_OUTPUT
### Deploy
- name: Install CLI tools from OpenShift Mirror
if: steps.triggers.outputs.triggered == 'true'
uses: redhat-actions/openshift-tools-installer@v1
with:
oc: "4"


# OC login and acquire short lived token
- if: steps.triggers.outputs.triggered == 'true'
shell: bash
run: |
# OC Login
OC_TEMP_TOKEN=$(curl -k -X POST ${{ inputs.oc_server }}/api/v1/namespaces/${{ secrets.oc_namespace }}/serviceaccounts/pipeline/token --header "Authorization: Bearer ${{ secrets.oc_token }}" -d '{"spec": {"expirationSeconds": 600}}' -H 'Content-Type: application/json; charset=utf-8' | jq -r '.status.token' )
oc login --token=$OC_TEMP_TOKEN --server=${{ inputs.oc_server }}
oc project ${{ secrets.oc_namespace }} # Safeguard!
# Only stop pre-existing deployments on PRs (status = pending-upgrade)
- if: steps.triggers.outputs.triggered == 'true' && github.event_name == 'pull_request'
run: |
# Interrupt any previous deployments (PR only)
PREVIOUS=$(helm status ${{ steps.vars.outputs.release }} -o json | jq .info.status || true)
if [[ ${PREVIOUS} =~ pending ]]; then
echo "Rollback triggered"
helm rollback ${{ steps.vars.outputs.release }} || \
helm uninstall ${{ steps.vars.outputs.release }}
fi
# Package Helm chart
- if: steps.triggers.outputs.triggered == 'true'
uses: actions/checkout@v4
- if: steps.triggers.outputs.triggered == 'true'
working-directory: ${{ inputs.directory }}
run: |
# Helm package
sed -i 's/^name:.*/name: ${{ github.event.repository.name }}/' Chart.yaml
helm package -u . --app-version="tag-${{ steps.vars.outputs.tag }}_run-${{ github.run_number }}" --version=${{ steps.pr.outputs.pr || steps.vars.outputs.version }}
# Deploy Helm chart as atomic, with timeout
- if: steps.triggers.outputs.triggered == 'true' && inputs.atomic != 'false'
working-directory: ${{ inputs.directory }}
run: |
# Helm upgrade/rollout - atomic, timeout
helm upgrade \
--set-string global.repository=${{ github.repository }} \
--set-string global.tag=${{ steps.vars.outputs.tag }} \
--set-string global.config.databaseUser=${{ inputs.db_user }} \
${{ inputs.params }} \
--install --wait --atomic ${{ steps.vars.outputs.release }} \
--timeout ${{ inputs.timeout-minutes }}m \
--values ${{ inputs.values }} \
./${{ github.event.repository.name }}-${{ steps.pr.outputs.pr || steps.vars.outputs.version }}.tgz
# Deploy Helm chart without atomic or timeout
- if: steps.triggers.outputs.triggered == 'true' && inputs.atomic == 'false'
working-directory: ${{ inputs.directory }}
run: |
# Helm upgrade/rollout - non-atomic, no timeout
helm upgrade \
--set-string global.repository=${{ github.repository }} \
--set-string global.tag=${{ steps.vars.outputs.tag }} \
${{ inputs.params }} \
${{ steps.vars.outputs.release }} \
--install --wait --values ${{ inputs.values }} \
./${{ github.event.repository.name }}-${{ steps.pr.outputs.pr || steps.vars.outputs.version }}.tgz
# Helm release history
- if: steps.triggers.outputs.triggered == 'true'
run: |
# Helm release history
helm history ${{ steps.vars.outputs.release }}
### Cleanup

# Completed pod cleanup
- if: steps.triggers.outputs.triggered == 'true'
run: |
# Completed pod cleanup
oc delete po --field-selector=status.phase==Succeeded || true
6 changes: 4 additions & 2 deletions .github/workflows/merge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,24 @@ jobs:
# https://github.com/bcgov/quickstart-openshift-helpers
deploy-test:
name: Deploy (test)
uses: bcgov/quickstart-openshift-helpers/.github/workflows/.deployer.yml@v0.8.1
uses: ./.github/workflows/.deployer.yml
secrets:
oc_namespace: ${{ secrets.OC_NAMESPACE }}
oc_token: ${{ secrets.OC_TOKEN }}
with:
environment: test
db_user: app

deploy-prod:
name: Deploy (prod)
needs: [deploy-test, vars]
uses: bcgov/quickstart-openshift-helpers/.github/workflows/.deployer.yml@v0.8.1
uses: ./.github/workflows/.deployer.yml
secrets:
oc_namespace: ${{ secrets.OC_NAMESPACE }}
oc_token: ${{ secrets.OC_TOKEN }}
with:
environment: prod
db_user: app
params:
--set backend.deploymentStrategy=RollingUpdate
--set frontend.deploymentStrategy=RollingUpdate
Expand Down
35 changes: 35 additions & 0 deletions .github/workflows/pr-close.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,38 @@ jobs:
with:
cleanup: helm
packages: backend frontend migrations
cleanup_db: # TODO move it off to another action later.
name: Remove DB User from crunchy.
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
name: Checkout
- name: Install CLI tools from OpenShift Mirror
uses: redhat-actions/openshift-tools-installer@v1
with:
oc: "4.14.37"
- name: OC Login
shell: bash
run: |
# OC Login
OC_TEMP_TOKEN=$(curl -k -X POST https://api.silver.devops.gov.bc.ca:6443/api/v1/namespaces/${{ secrets.oc_namespace }}/serviceaccounts/pipeline/token --header "Authorization: Bearer ${{ secrets.oc_token }}" -d '{"spec": {"expirationSeconds": 600}}' -H 'Content-Type: application/json; charset=utf-8' | jq -r '.status.token' )
oc login --token=$OC_TEMP_TOKEN --server=https://api.silver.devops.gov.bc.ca:6443
oc project ${{ secrets.oc_namespace }} # Safeguard!
- name: Remove PR user and database from crunchy.
shell: bash
run: |
USER_TO_REMOVE='{"databases":["app-${{ github.event.number }}"],"name":"app-${{ github.event.number }}"}'
echo 'getting current users from crunchy'
CURRENT_USERS=$(oc get PostgresCluster/postgres-crunchy -o json | jq '.spec.users')
echo "${CURRENT_USERS}"
# Remove the user from the list,
UPDATED_USERS=$(echo "${CURRENT_USERS}" | jq --argjson user "${USER_TO_REMOVE}" 'map(select(. != $user))')
PATCH_JSON=$(jq -n --argjson users "${UPDATED_USERS}" '{"spec": {"users": $users}}')
oc patch PostgresCluster/postgres-crunchy --type=merge -p "${PATCH_JSON}"
exit 0
Loading

0 comments on commit 58e34f3

Please sign in to comment.