diff --git a/.github/graphics/analysis.png b/.github/graphics/analysis.png new file mode 100644 index 000000000..31e825a74 Binary files /dev/null and b/.github/graphics/analysis.png differ diff --git a/.github/graphics/branch-protection.png b/.github/graphics/branch-protection.png new file mode 100644 index 000000000..c7a3c728e Binary files /dev/null and b/.github/graphics/branch-protection.png differ diff --git a/common/graphics/deploymentUpdate.png b/.github/graphics/deploymentUpdate.png similarity index 100% rename from common/graphics/deploymentUpdate.png rename to .github/graphics/deploymentUpdate.png diff --git a/.github/graphics/merge.png b/.github/graphics/merge.png new file mode 100644 index 000000000..780a220e0 Binary files /dev/null and b/.github/graphics/merge.png differ diff --git a/common/graphics/mergeNotification.png b/.github/graphics/mergeNotification.png similarity index 100% rename from common/graphics/mergeNotification.png rename to .github/graphics/mergeNotification.png diff --git a/.github/graphics/packages.png b/.github/graphics/packages.png new file mode 100644 index 000000000..69659a783 Binary files /dev/null and b/.github/graphics/packages.png differ diff --git a/common/graphics/pr-cleanup.png b/.github/graphics/pr-cleanup.png similarity index 100% rename from common/graphics/pr-cleanup.png rename to .github/graphics/pr-cleanup.png diff --git a/.github/graphics/pr-close.png b/.github/graphics/pr-close.png new file mode 100644 index 000000000..68eb0d29c Binary files /dev/null and b/.github/graphics/pr-close.png differ diff --git a/.github/graphics/pr-open.png b/.github/graphics/pr-open.png new file mode 100644 index 000000000..bd4bfe131 Binary files /dev/null and b/.github/graphics/pr-open.png differ diff --git a/.github/graphics/pr-validate.png b/.github/graphics/pr-validate.png new file mode 100644 index 000000000..2e8a5f442 Binary files /dev/null and b/.github/graphics/pr-validate.png differ diff --git a/.github/graphics/scheduled.png b/.github/graphics/scheduled.png new file mode 100644 index 000000000..a1f8d33f1 Binary files /dev/null and b/.github/graphics/scheduled.png differ diff --git a/.github/graphics/schemaspy.png b/.github/graphics/schemaspy.png new file mode 100644 index 000000000..53fe254f4 Binary files /dev/null and b/.github/graphics/schemaspy.png differ diff --git a/.github/graphics/template.png b/.github/graphics/template.png new file mode 100644 index 000000000..7841f9c9e Binary files /dev/null and b/.github/graphics/template.png differ diff --git a/.github/workflows/.tests.yml b/.github/workflows/.tests.yml new file mode 100644 index 000000000..81a8ac744 --- /dev/null +++ b/.github/workflows/.tests.yml @@ -0,0 +1,56 @@ +name: .Tests + +on: + workflow_call: + inputs: + ### Required + target: + description: PR number, test or prod + required: true + type: string + + ### Typical / recommended + triggers: + description: Bash array to diff for build triggering; omit to always fire + required: false + type: string + +env: + DOMAIN: apps.silver.devops.gov.bc.ca + PREFIX: ${{ github.event.repository.name }}-${{ inputs.target }} + +jobs: + cypress-tests: + env: + DOMAIN: apps.silver.devops.gov.bc.ca + PREFIX: ${{ github.event.repository.name }}-${{ inputs.target }} + runs-on: ubuntu-latest + steps: + - name: Checkout GitCode + uses: actions/checkout@v3 + + - name: Debug secrets + run: | + echo "Checking secrets..." + echo "auth_base_url: ${{ vars.KEYCLOAK_URL_DEV }}" + echo "auth_realm: ${{ vars.KEYCLOAK_REALM }}" + echo "keycloak_user: ${{ vars.KEYCLOAK_USER }}" + echo "keycloak_client_id: ${{ vars.KEYCLOAK_CLIENT_ID }}" + + env: + KEYCLOAK_PASSWORD: ${{ secrets.KEYCLOAK_PASSWORD }} + + - name: Run Cypress Test + uses: cypress-io/github-action@v5 + with: + working-directory: ./frontend + command: npx cypress run --browser electron --config baseUrl=https://${{ env.PREFIX }}-frontend.${{ env.DOMAIN }} --env auth_base_url=${{ vars.KEYCLOAK_URL_DEV }},auth_realm=${{ vars.KEYCLOAK_REALM }},auth_client_id=${{ vars.KEYCLOAK_CLIENT_ID }},keycloak_user=${{ vars.KEYCLOAK_USER }},keycloak_password=${{ secrets.KEYCLOAK_PASSWORD }} + + - name: Upload Artifacts + uses: actions/upload-artifact@v3 + if: always() + with: + name: cypress-artifacts + path: |- + /home/runner/work/nr-compliance-enforcement/nr-compliance-enforcement/frontend/cypress/videos/ + /home/runner/work/nr-compliance-enforcement/nr-compliance-enforcement/frontend/cypress/screenshots/ diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml new file mode 100644 index 000000000..7b9f7e2b1 --- /dev/null +++ b/.github/workflows/analysis.yml @@ -0,0 +1,89 @@ +name: Analysis + +on: + push: + branches: [main] + pull_request: + types: [opened, reopened, synchronize, ready_for_review, converted_to_draft] + schedule: + - cron: "0 11 * * 0" # 3 AM PST = 12 PM UDT, runs sundays + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + tests: + name: Tests + if: ${{ ! github.event.pull_request.draft }} + runs-on: ubuntu-22.04 + timeout-minutes: 5 + services: + postgres: + image: postgres + env: + POSTGRES_PASSWORD: postgres + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 5432:5432 + strategy: + matrix: + dir: [backend, frontend] + include: + - dir: backend + token: SONAR_TOKEN_BACKEND + - dir: frontend + token: SONAR_TOKEN_FRONTEND + steps: + - uses: bcgov-nr/action-test-and-analyse@v1.2.1 + with: + commands: | + npm ci + npm run test:cov + dir: ${{ matrix.dir }} + node_version: "22" + sonar_args: > + -Dsonar.exclusions=**/coverage/**,**/node_modules/**,**/*spec.ts + -Dsonar.organization=bcgov-sonarcloud + -Dsonar.projectKey=quickstart-openshift_${{ matrix.dir }} + -Dsonar.sources=src + -Dsonar.tests.inclusions=**/*spec.ts + -Dsonar.javascript.lcov.reportPaths=./coverage/lcov.info + sonar_token: ${{ secrets[matrix.token] }} + triggers: ('${{ matrix.dir }}/') + + # https://github.com/marketplace/actions/aqua-security-trivy + trivy: + name: Trivy Security Scan + if: ${{ ! github.event.pull_request.draft }} + runs-on: ubuntu-22.04 + timeout-minutes: 1 + steps: + - uses: actions/checkout@v4 + - name: Run Trivy vulnerability scanner in repo mode + uses: aquasecurity/trivy-action@0.23.0 + with: + format: "sarif" + output: "trivy-results.sarif" + ignore-unfixed: true + scan-type: "fs" + scanners: "vuln,secret,config" + severity: "CRITICAL,HIGH" + + - name: Upload Trivy scan results to GitHub Security tab + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: "trivy-results.sarif" + + results: + name: Analysis Results + needs: [tests, trivy] + runs-on: ubuntu-22.04 + steps: + - run: echo "Success!" + diff --git a/.github/workflows/deploy-nats.yml b/.github/workflows/deploy-nats.yml index b52b73b16..6f60ce0b5 100644 --- a/.github/workflows/deploy-nats.yml +++ b/.github/workflows/deploy-nats.yml @@ -54,3 +54,9 @@ jobs: run: | RELEASE_NAME=${{ github.event.repository.name }}-${{ github.event.number }}-nats oc label statefulset $RELEASE_NAME app=${{ github.event.repository.name }}-${{ github.event.number }} + - name: Label NATS PVCs + run: | + RELEASE_NAME=${{ github.event.repository.name }}-${{ github.event.number }}-nats + for pvc in $(oc get pvc -l release=$RELEASE_NAME -o name); do + oc label $pvc app=${{ github.event.repository.name }}-${{ github.event.number }} + done diff --git a/.github/workflows/merge-main.yml b/.github/workflows/merge-main.yml index 83ee0da04..42cfb54ea 100644 --- a/.github/workflows/merge-main.yml +++ b/.github/workflows/merge-main.yml @@ -1,325 +1,76 @@ -name: Merge to Main +name: Merge on: push: - branches: - - main + branches: [main] paths-ignore: - - ".github/ISSUE_TEMPLATE/*" - - "**.md" + - "*.md" + - ".github/**" + - ".github/graphics/**" + - "!.github/workflows/**" workflow_dispatch: + inputs: + pr_no: + description: "PR-numbered container set to deploy" + type: number + required: true concurrency: + # Do not interrupt previous workflows group: ${{ github.workflow }} - cancel-in-progress: true + cancel-in-progress: false jobs: - codeql: - name: Semantic Code Analysis + vars: + name: Set Variables + outputs: + pr: ${{ steps.pr.outputs.pr }} runs-on: ubuntu-22.04 - permissions: - actions: read - contents: read - security-events: write - steps: - - uses: actions/checkout@v3 - - - name: Initialize - uses: github/codeql-action/init@v2 - with: - languages: javascript - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below). - - name: Autobuild - uses: github/codeql-action/autobuild@v2 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 - - deploys-test-nats: - name: Deploy NATS to TEST - environment: test - runs-on: ubuntu-22.04 - steps: - - name: Set up OpenShift CLI - uses: redhat-actions/oc-login@v1 - with: - openshift_server_url: ${{ vars.OC_SERVER }} - openshift_token: ${{ secrets.OC_TOKEN }} - namespace: ${{ vars.OC_NAMESPACE }} - - - name: Add NATS Helm repo - run: helm repo add nats https://nats-io.github.io/k8s/helm/charts/ - - - name: Check if NATS release exists in TEST - run: | - RELEASE_NAME=${{ github.event.repository.name }}-test-nats - if helm list -q | grep -q $RELEASE_NAME; then - echo "TEST Release $RELEASE_NAME already exists. Skipping install." - echo "release_exists=true" >> $GITHUB_ENV - else - echo "TEST Release $RELEASE_NAME does not exist. Proceeding with install." - echo "release_exists=false" >> $GITHUB_ENV - fi - - - name: Deploy NATS to TEST using Helm - if: env.release_exists == 'false' - run: | - helm install ${{ github.event.repository.name }}-test-nats nats/nats \ - --set config.jetstream.enabled=true \ - --set config.jetstream.fileStore.pvc.size=200Mi \ - --set config.jetstream.memoryStore.enabled=true \ - --set config.jetstream.memoryStore.maxSize=250Mi \ - --set cluster.enabled=true \ - --set natsBox.enabled=false \ - --set persistence.enabled=true \ - --set persistence.size=200Mi \ - --set container.merge.resources.requests.cpu=100m \ - --set container.merge.resources.limits.cpu=200m \ - --set container.merge.resources.requests.memory=100Mi \ - --set container.merge.resources.limits.memory=400Mi \ - --set reloader.enabled=false \ - --set replicaCount=1 - - deploys-test-database: - name: Deploy Database to TEST - needs: codeql - environment: test - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v3 - - - name: Set up OpenShift CLI - uses: redhat-actions/oc-login@v1 - with: - openshift_server_url: ${{ vars.OC_SERVER }} - openshift_token: ${{ secrets.OC_TOKEN }} - namespace: ${{ vars.OC_NAMESPACE }} - - - name: Deploy Database - uses: bcgov-nr/action-deployer-openshift@v2.3.0 - with: - file: database/openshift.deploy.yml - oc_namespace: ${{ vars.OC_NAMESPACE }} - oc_server: ${{ vars.OC_SERVER }} - oc_token: ${{ secrets.OC_TOKEN }} - overwrite: false - parameters: -p ZONE=test - -p NAME=${{ github.event.repository.name }} - -p PROMOTE=${{ github.repository }}/database:test - penetration_test: false - - deploys-test-backend: - name: Deploy Backend to TEST - needs: - - deploys-test-database - environment: test - runs-on: ubuntu-22.04 - steps: - - uses: bcgov-nr/action-deployer-openshift@v2.3.0 - with: - file: backend/openshift.deploy.yml - oc_namespace: ${{ vars.OC_NAMESPACE }} - oc_server: ${{ vars.OC_SERVER }} - oc_token: ${{ secrets.OC_TOKEN }} - overwrite: true - parameters: -p ZONE=test -p PROMOTE=${{ github.repository }}/backend:test - -p NAME=${{ github.event.repository.name }} - -p PROMOTE_MIGRATION=${{ github.repository }}/database-migrations:test - -p FLYWAY_LOCATIONS="filesystem:./sql, filesystem:./sql-test" - penetration_test: false - - deploys-test: - name: TEST Deployments - needs: - - codeql - - deploys-test-nats - - deploys-test-backend - environment: test - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v3 - - name: Set up OpenShift CLI - uses: redhat-actions/oc-login@v1 - with: - openshift_server_url: ${{ vars.OC_SERVER }} - openshift_token: ${{ secrets.OC_TOKEN }} - namespace: ${{ vars.OC_NAMESPACE }} - - - name: Deploy Components - uses: bcgov-nr/action-deployer-openshift@v2.3.0 - with: - file: ${{ matrix.file }} - oc_namespace: ${{ vars.OC_NAMESPACE }} - oc_server: ${{ vars.OC_SERVER }} - oc_token: ${{ secrets.OC_TOKEN }} - overwrite: ${{ matrix.overwrite }} - parameters: -p ZONE=test -p PROMOTE=${{ github.repository }}/${{ matrix.name }}:test - -p NAME=${{ github.event.repository.name }} ${{ matrix.parameters }} - penetration_test: false - strategy: - matrix: - name: [frontend, init, webeoc] - include: - - name: webeoc - file: webeoc/openshift.deploy.yml - overwrite: true - - name: frontend - file: frontend/openshift.deploy.yml - parameters: -p KEYCLOAK_URL=${{ vars.KEYCLOAK_URL_TEST }} - -p COMS_URL=${{ vars.COMS_URL_TEST }} - -p COMS_BUCKET=${{ vars.COMS_BUCKET_TEST }} - -p ENVIRONMENT_NAME=${{ vars.ENVIRONMENT_NAME_TEST }} - overwrite: true - - name: init - file: common/openshift.init.yml - overwrite: false - - deploys-prod-nats: - name: Deploy NATS to PROD - needs: - - deploys-test - environment: prod - runs-on: ubuntu-22.04 - steps: - - name: Set up OpenShift CLI - uses: redhat-actions/oc-login@v1 - with: - openshift_server_url: ${{ vars.OC_SERVER }} - openshift_token: ${{ secrets.OC_TOKEN }} - namespace: ${{ vars.OC_NAMESPACE }} - - - name: Add NATS Helm repo - run: helm repo add nats https://nats-io.github.io/k8s/helm/charts/ - - - name: Check if NATS release exists in PROD - run: | - RELEASE_NAME=${{ github.event.repository.name }}-prod-nats - if helm list -q | grep -q $RELEASE_NAME; then - echo "PROD Release $RELEASE_NAME already exists. Skipping install." - echo "release_exists=true" >> $GITHUB_ENV - else - echo "PROD Release $RELEASE_NAME does not exist. Proceeding with install." - echo "release_exists=false" >> $GITHUB_ENV - fi - - - name: Deploy NATS to PROD using Helm - if: env.release_exists == 'false' - run: | - helm install ${{ github.event.repository.name }}-prod-nats nats/nats \ - --set config.jetstream.enabled=true \ - --set config.jetstream.fileStore.pvc.size=200Mi \ - --set config.jetstream.memoryStore.enabled=true \ - --set config.jetstream.memoryStore.maxSize=250Mi \ - --set cluster.enabled=true \ - --set natsBox.enabled=false \ - --set persistence.enabled=true \ - --set persistence.size=200Mi \ - --set container.merge.resources.requests.cpu=100m \ - --set container.merge.resources.limits.cpu=200m \ - --set container.merge.resources.requests.memory=100Mi \ - --set container.merge.resources.limits.memory=400Mi \ - --set reloader.enabled=false \ - --set replicaCount=1 - - deploys-prod-database: - name: Deploy Database to PROD - needs: deploys-test - environment: prod - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v3 - - - name: Set up OpenShift CLI - uses: redhat-actions/oc-login@v1 - with: - openshift_server_url: ${{ vars.OC_SERVER }} - openshift_token: ${{ secrets.OC_TOKEN }} - namespace: ${{ vars.OC_NAMESPACE }} - - - name: Deploy Database - uses: bcgov-nr/action-deployer-openshift@v2.3.0 - with: - file: database/openshift.deploy.yml - oc_namespace: ${{ vars.OC_NAMESPACE }} - oc_server: ${{ vars.OC_SERVER }} - oc_token: ${{ secrets.OC_TOKEN }} - overwrite: false - parameters: -p ZONE=prod - -p NAME=${{ github.event.repository.name }} - -p PROMOTE=${{ github.repository }}/database:test - penetration_test: false - - deploys-prod-backend: - name: Deploy Backend to PROD - needs: - - deploys-prod-database - environment: prod - runs-on: ubuntu-22.04 - steps: - - uses: bcgov-nr/action-deployer-openshift@v2.3.0 - with: - file: backend/openshift.deploy.yml - oc_namespace: ${{ vars.OC_NAMESPACE }} - oc_server: ${{ vars.OC_SERVER }} - oc_token: ${{ secrets.OC_TOKEN }} - overwrite: true - parameters: -p ZONE=prod -p PROMOTE=${{ github.repository }}/backend:test - -p NAME=${{ github.event.repository.name }} - -p PROMOTE_MIGRATION=${{ github.repository }}/database-migrations:test - -p FLYWAY_LOCATIONS="filesystem:./sql" - penetration_test: false - - deploys-prod: - name: Deploy Other Components to PROD - needs: - - deploys-prod-nats - - deploys-prod-backend - environment: prod - runs-on: ubuntu-22.04 - strategy: - matrix: - name: [frontend, init, webeoc] - include: - - name: webeoc - file: webeoc/openshift.deploy.yml - overwrite: true - - name: frontend - file: frontend/openshift.deploy.yml - parameters: -p KEYCLOAK_URL=${{ vars.KEYCLOAK_URL_PROD }} - -p COMS_URL=${{ vars.COMS_URL_PROD }} - -p COMS_BUCKET=${{ vars.COMS_BUCKET_PROD }} - overwrite: true - - name: init - file: common/openshift.init.yml - overwrite: false + timeout-minutes: 1 steps: - - uses: bcgov-nr/action-deployer-openshift@v2.3.0 - with: - file: ${{ matrix.file }} - oc_namespace: ${{ vars.OC_NAMESPACE }} - oc_server: ${{ vars.OC_SERVER }} - oc_token: ${{ secrets.OC_TOKEN }} - overwrite: ${{ matrix.overwrite }} - parameters: -p ZONE=prod -p PROMOTE=${{ github.repository }}/${{ matrix.name }}:test - -p NAME=${{ github.event.repository.name }} ${{ matrix.parameters }} - penetration_test: false - - image-promotions: - name: Promote images to PROD - needs: - - deploys-prod + # Get PR number for squash merges to main + - name: PR Number + id: pr + uses: bcgov-nr/action-get-pr@v0.0.1 + + # https://github.com/bcgov/quickstart-openshift-helpers + deploy-test: + name: Deploy (test) + uses: bcgov/quickstart-openshift-helpers/.github/workflows/.deployer.yml@v0.5.0 + secrets: + oc_namespace: ${{ secrets.OC_NAMESPACE }} + oc_token: ${{ secrets.OC_TOKEN }} + with: + environment: test + + deploy-prod: + name: Deploy (prod) + needs: [deploy-test, vars] + uses: bcgov/quickstart-openshift-helpers/.github/workflows/.deployer.yml@v0.5.0 + secrets: + oc_namespace: ${{ secrets.OC_NAMESPACE }} + oc_token: ${{ secrets.OC_TOKEN }} + with: + environment: prod + params: --set backend.deploymentStrategy=RollingUpdate + --set frontend.deploymentStrategy=RollingUpdate + --set global.autoscaling=true + --set frontend.pdb.enabled=true + --set backend.pdb.enabled=true + promote: + name: Promote Images + needs: [deploy-prod, vars] runs-on: ubuntu-22.04 permissions: packages: write strategy: matrix: - component: [backend, database, database-migrations, frontend, webeoc] + package: [migrations, backend, frontend, webeoc] + timeout-minutes: 1 steps: - - uses: shrink/actions-docker-registry-tag@v3 + - uses: shrink/actions-docker-registry-tag@v4 with: registry: ghcr.io - repository: ${{ github.repository }}/${{ matrix.component }} - target: test + repository: ${{ github.repository }}/${{ matrix.package }} + target: ${{ needs.vars.outputs.pr }} tags: prod diff --git a/.github/workflows/pr-close.yml b/.github/workflows/pr-close.yml index 08f0d7cfe..ebd159daf 100644 --- a/.github/workflows/pr-close.yml +++ b/.github/workflows/pr-close.yml @@ -1,48 +1,21 @@ -name: Pull Request Closed +name: PR Closed on: pull_request: - types: - - closed + types: [closed] concurrency: # PR open and close use the same group, allowing only one at a time - group: pr-${{ github.workflow }}-${{ github.event.number }} + group: ${{ github.event.number }} cancel-in-progress: true jobs: - # Clean up OpenShift when PR closed, no conditions - cleanup-openshift: - name: Cleanup OpenShift - runs-on: ubuntu-22.04 - steps: - - name: Remove OpenShift artifacts - run: | - oc login --token=${{ secrets.OC_TOKEN }} --server=${{ vars.OC_SERVER }} - oc project ${{ vars.OC_NAMESPACE }} - - # Remove old build runs, build pods and deployment pods - oc delete all,pvc,secret -l app=${{ github.event.repository.name }}-${{ github.event.number }} - - - name: Uninstall NATS Helm Release - run: | - RELEASE_NAME=${{ github.event.repository.name }}-${{ github.event.number }}-nats - helm uninstall $RELEASE_NAME - - # If merged into main, then handle any image promotions - image-promotions: - name: Image Promotions - if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'main' - runs-on: ubuntu-22.04 - permissions: - packages: write - strategy: - matrix: - package: [backend, database, database-migrations, frontend, webeoc] - steps: - - uses: shrink/actions-docker-registry-tag@v3 - with: - registry: ghcr.io - repository: ${{ github.repository }}/${{ matrix.package }} - target: ${{ github.event.number }} - tags: test + cleanup: + name: Cleanup and Images + uses: bcgov/quickstart-openshift-helpers/.github/workflows/.pr-close.yml@v0.5.0 + secrets: + oc_namespace: ${{ secrets.OC_NAMESPACE }} + oc_token: ${{ secrets.OC_TOKEN }} + with: + cleanup: helm + packages: backend frontend migrations diff --git a/.github/workflows/pr-open.yml b/.github/workflows/pr-open.yml index 8da6afd2a..3bb7b6ba6 100644 --- a/.github/workflows/pr-open.yml +++ b/.github/workflows/pr-open.yml @@ -1,159 +1,57 @@ -name: Pull Request +name: PR on: pull_request: concurrency: - # PR open and close use the same group, allowing only one at a time - group: pr-${{ github.workflow }}-${{ github.event.number }} + # Cancel in progress for PR open and close + group: ${{ github.event.number }} cancel-in-progress: true jobs: - pr-greeting: - name: PR Greeting - env: - DOMAIN: apps.silver.devops.gov.bc.ca - PREFIX: ${{ github.event.repository.name }}-${{ github.event.number }} - runs-on: ubuntu-22.04 - permissions: - pull-requests: write - steps: - - name: PR Greeting - uses: bcgov-nr/action-pr-description-add@v0.0.2 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - add_markdown: | - --- - - Thanks for the PR! - - Any successful deployments (not always required) will be available below. - [Backend](https://${{ env.PREFIX }}-frontend.${{ env.DOMAIN }}/api/) available - [Frontend](https://${{ env.PREFIX }}-frontend.${{ env.DOMAIN }}/) available - - Once merged, code will be promoted and handed off to following workflow run. - [Main Merge Workflow](https://github.com/${{ github.repository }}/actions/workflows/merge-main.yml) - + # https://github.com/bcgov-nr/action-builder-ghcr builds: name: Builds runs-on: ubuntu-22.04 - permissions: - packages: write strategy: matrix: - package: [backend, database, database-migrations, frontend, webeoc] - include: - - package: backend - triggers: ('backend/') - build_file: ./backend/Dockerfile - build_context: ./backend - - package: webeoc - triggers: ('webeoc/') - build_file: ./webeoc/Dockerfile - build_context: ./webeoc - - package: database - triggers: ('database/') - build_file: ./database/Dockerfile - build_context: ./database - - package: frontend - triggers: ('frontend/') - build_file: ./frontend/Dockerfile - build_context: ./frontend - - package: database-migrations - triggers: ('backend/db') - build_file: ./backend/db/Dockerfile - build_context: ./backend/db + package: [backend, frontend, migrations, webeoc] + timeout-minutes: 10 steps: - - uses: actions/checkout@v3 - - uses: bcgov-nr/action-builder-ghcr@v1.3.0 + - uses: bcgov-nr/action-builder-ghcr@v2.0.2 with: + keep_versions: 50 package: ${{ matrix.package }} tag: ${{ github.event.number }} - tag_fallback: test - token: ${{ secrets.GITHUB_TOKEN }} - triggers: ${{ matrix.triggers }} - build_file: ${{ matrix.build_file }} - build_context: ${{ matrix.build_context }} + tag_fallback: latest + triggers: ('${{ matrix.package }}/') + + # https://github.com/bcgov/quickstart-openshift-helpers deploys: name: Deploys - needs: - - builds - environment: dev + needs: [builds] + uses: bcgov/quickstart-openshift-helpers/.github/workflows/.deployer.yml@v0.5.0 + secrets: + oc_namespace: ${{ secrets.OC_NAMESPACE }} + oc_token: ${{ secrets.OC_TOKEN }} + with: + triggers: ('backend/' 'frontend/' 'webeoc/' 'migrations/') + params: --set global.secrets.persist=false + + tests: + name: Tests + if: needs.deploys.outputs.triggered == 'true' + needs: [deploys] + uses: ./.github/workflows/.tests.yml + + with: + target: ${{ github.event.number }} + secrets: inherit # so that the tests github action can use the secrests that this action has access to + + results: + name: PR Results + needs: [builds, deploys, tests] + if: always() && (!failure()) && (!cancelled()) runs-on: ubuntu-22.04 - strategy: - matrix: - name: [backend, database, init, frontend, webeoc] - include: - - name: backend - file: backend/openshift.deploy.yml - overwrite: true - parameters: -p MIN_REPLICAS=1 -p MAX_REPLICAS=2 - -p PROMOTE_MIGRATION=${{ github.repository }}/database-migrations:${{ github.event.number }} - -p CPU_REQUEST=40m - -p CPU_LIMIT=80m - -p MEMORY_REQUEST=100Mi - -p MEMORY_LIMIT=200Mi - -p FLYWAY_LOCATIONS="filesystem:./sql, filesystem:./sql-test" - - name: webeoc - file: webeoc/openshift.deploy.yml - overwrite: true - needs: [backend] - parameters: -p MIN_REPLICAS=1 -p MAX_REPLICAS=1 - - name: database - file: database/openshift.deploy.yml - overwrite: false - parameters: -p CPU_REQUEST=100m - -p CPU_LIMIT=200m - -p MEMORY_REQUEST=250Mi - -p MEMORY_LIMIT=500Mi - - name: frontend - file: frontend/openshift.deploy.yml - overwrite: true - parameters: -p MIN_REPLICAS=1 -p MAX_REPLICAS=2 - -p KEYCLOAK_URL=${{ vars.KEYCLOAK_URL_DEV}} - -p COMS_URL=${{vars.COMS_URL_DEV}} - -p COMS_BUCKET=${{vars.COMS_BUCKET_DEV}} - -p CPU_REQUEST=25m - -p CPU_LIMIT=50m - -p MEMORY_REQUEST=40Mi - -p MEMORY_LIMIT=80Mi - -p ENVIRONMENT_NAME=${{ vars.ENVIRONMENT_NAME_DEV }} - - name: init - file: common/openshift.init.yml - overwrite: false - steps: - - uses: bcgov-nr/action-deployer-openshift@v2.3.0 - with: - file: ${{ matrix.file }} - oc_namespace: ${{ vars.OC_NAMESPACE }} - oc_server: ${{ vars.OC_SERVER }} - oc_token: ${{ secrets.OC_TOKEN }} - overwrite: ${{ matrix.overwrite }} - penetration_test: false - parameters: -p ZONE=${{ github.event.number }} -p NAME=${{ github.event.repository.name }} - -p PROMOTE=${{ github.repository }}/${{ matrix.name }}:${{ github.event.number }} - ${{ matrix.parameters }} - cypress-tests: - needs: deploys - env: - DOMAIN: apps.silver.devops.gov.bc.ca - PREFIX: ${{ github.event.repository.name }}-${{ github.event.number }} - runs-on: ubuntu-latest steps: - - name: Checkout GitCode - uses: actions/checkout@v3 - - - name: Run Cypress Test - uses: cypress-io/github-action@v5 - with: - working-directory: ./frontend - command: npx cypress run --browser electron --config baseUrl=https://${{ env.PREFIX }}-frontend.${{ env.DOMAIN }} --env auth_base_url=${{ vars.KEYCLOAK_URL_DEV }},auth_realm=${{ vars.KEYCLOAK_REALM }},auth_client_id=${{ vars.KEYCLOAK_CLIENT_ID }},keycloak_user=${{ vars.KEYCLOAK_USER }},keycloak_password=${{ secrets.KEYCLOAK_PASSWORD }} - - - name: Upload Artifacts - uses: actions/upload-artifact@v3 - if: always() - with: - name: cypress-artifacts - path: |- - /home/runner/work/nr-compliance-enforcement/nr-compliance-enforcement/frontend/cypress/videos/ - /home/runner/work/nr-compliance-enforcement/nr-compliance-enforcement/frontend/cypress/screenshots/ + - run: echo "Success!" diff --git a/.github/workflows/pr-validate.yml b/.github/workflows/pr-validate.yml new file mode 100644 index 000000000..b1b75ccb1 --- /dev/null +++ b/.github/workflows/pr-validate.yml @@ -0,0 +1,27 @@ +name: PR Validate + +on: + pull_request: + types: [edited, opened, synchronize, reopened, ready_for_review] + +concurrency: + group: ${{ github.workflow }}-edit-${{ github.event.number }} + cancel-in-progress: true + +jobs: + validate: + name: Validate PR + if: (! github.event.pull_request.draft) + uses: bcgov/quickstart-openshift-helpers/.github/workflows/.pr-validate.yml@v0.5.0 + with: + markdown_links: | + - [Frontend](https://${{ github.event.repository.name }}-${{ github.event.number }}-frontend.apps.silver.devops.gov.bc.ca) + - [Backend](https://${{ github.event.repository.name }}-${{ github.event.number }}-frontend.apps.silver.devops.gov.bc.ca/api) + + results: + name: Validate Results + if: always() + needs: [validate] + runs-on: ubuntu-22.04 + steps: + - run: echo "Success!" diff --git a/.github/workflows/scheduled.yml b/.github/workflows/scheduled.yml new file mode 100644 index 000000000..2252957c2 --- /dev/null +++ b/.github/workflows/scheduled.yml @@ -0,0 +1,126 @@ +name: Scheduled + +on: + schedule: [cron: "0 11 * * 6"] # 3 AM PST = 12 PM UDT, Saturdays + workflow_dispatch: + workflow_call: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + ageOutPRs: + name: PR Env Purge + env: + # https://tecadmin.net/getting-yesterdays-date-in-bash/ + CUTOFF: "1 week ago" + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Clean up Helm Releases + run: | + oc login --token=${{ secrets.OC_TOKEN }} --server=${{ vars.OC_SERVER }} + oc project ${{ secrets.OC_NAMESPACE }} # Safeguard! + + # Catch errors, unset variables, and pipe failures (e.g. grep || true ) + set -euo pipefail + + # Echos + echo "Delete stale Helm releases" + echo "Cutoff: ${{ env.CUTOFF }}" + + # Before date, list of releases + BEFORE=$(date +%s -d "${{ env.CUTOFF }}") + RELEASES=$(helm ls -aq | grep ${{ github.event.repository.name }} || :) + + # If releases, then iterate + [ -z "${RELEASES}" ]|| for r in ${RELEASES[@]}; do + + # Get last update and convert the date + UPDATED=$(date "+%s" -d <<< echo $(helm status $r -o json | jq -r .info.last_deployed)) + + # Compare to cutoff and delete as necessary + if [[ ${UPDATED} < ${BEFORE} ]]; then + echo -e "\nOlder than cutoff: ${r}" + helm uninstall --no-hooks ${r} + oc delete pvc/${r}-bitnami-pg-0 || true + else + echo -e "\nNewer than cutoff: ${r}" + echo "No need to delete" + fi + done + + generate-schema-spy: + name: Generate SchemaSpy Documentation + runs-on: ubuntu-22.04 + services: + postgres: + image: postgis/postgis:16-3.4 + env: + POSTGRES_DB: default + POSTGRES_USER: postgres + POSTGRES_PASSWORD: default + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 5432:5432 + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + - name: Flyway + uses: docker://flyway/flyway:10 + env: + FLYWAY_URL: jdbc:postgresql://postgres:5432/default + FLYWAY_USER: postgres + FLYWAY_PASSWORD: default + FLYWAY_DEFAULT_SCHEMA: "public" + with: + args: info migrate info + + - name: Create Output Folder + run: | + mkdir output + chmod a+rwx -R output + - name: Run Schemaspy + run: docker run --network host -v "$PWD/output:/output" schemaspy/schemaspy:6.2.4 -t pgsql11 -db default -host 127.0.0.1 -port 5432 -u postgres -p default -schemas users + - name: Deploy to Pages + uses: JamesIves/github-pages-deploy-action@v4 + with: + folder: output + target-folder: schemaspy + + tests: + name: Tests + uses: ./.github/workflows/.tests.yml + with: + target: test + + # Run sequentially to reduce chances of rate limiting + zap_scan: + runs-on: ubuntu-latest + name: ZAP Scans + env: + DOMAIN: apps.silver.devops.gov.bc.ca + PREFIX: ${{ github.event.repository.name }}-test + steps: + - name: ZAP Scan + uses: zaproxy/action-full-scan@v0.10.0 + with: + allow_issue_writing: true + artifact_name: "zap_backend" + cmd_options: "-a" + issue_title: "ZAP: Backend" + target: https://${{ env.PREFIX }}-frontend.${{ env.DOMAIN }}/api + + - name: ZAP Scan - Frontend + uses: zaproxy/action-full-scan@v0.10.0 + with: + allow_issue_writing: true + artifact_name: "zap_frontend" + cmd_options: "-a" + issue_title: "ZAP: Frontend" + target: https://${{ env.PREFIX }}-frontend.${{ env.DOMAIN }} diff --git a/.github/workflows/schemaspy.yaml b/.github/workflows/schemaspy.yaml deleted file mode 100644 index e443ce399..000000000 --- a/.github/workflows/schemaspy.yaml +++ /dev/null @@ -1,52 +0,0 @@ -name: Generate Schemaspy Docs -on: - workflow_dispatch: - -# pull_request: - push: - branches: - - main - -jobs: - generate-schema-spy: - name: Generate SchemaSpy Documentation - runs-on: ubuntu-22.04 - services: - postgres: - image: postgis/postgis:16-3.4 - env: - POSTGRES_DB: default - POSTGRES_USER: postgres - POSTGRES_PASSWORD: default - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - - 5432:5432 - - steps: - - uses: actions/checkout@v4 - - name: Flyway - uses: docker://flyway/flyway:10 - env: - FLYWAY_URL: jdbc:postgresql://postgres:5432/default - FLYWAY_USER: postgres - FLYWAY_PASSWORD: default - FLYWAY_LOCATIONS: filesystem:./backend/db/migrations - FLYWAY_DEFAULT_SCHEMA: "public" - with: - args: info migrate info - - - name: Create Output Folder - run: | - mkdir output - chmod a+rwx -R output - - name: Run Schemaspy - run: docker run --network host -v "$PWD/output:/output" schemaspy/schemaspy:6.2.4 -t pgsql11 -db default -host 127.0.0.1 -port 5432 -u postgres -p default -schemas public - - name: Deploy to Pages - uses: JamesIves/github-pages-deploy-action@v4 - with: - folder: output - target-folder: schemaspy \ No newline at end of file diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml deleted file mode 100644 index a261194d4..000000000 --- a/.github/workflows/unit-tests.yml +++ /dev/null @@ -1,67 +0,0 @@ -name: Unit Tests and Analysis - -on: - pull_request: - types: - - opened - - reopened - - synchronize - - ready_for_review - push: - branches: - - main - workflow_dispatch: - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - tests: - name: Unit Tests - if: github.event_name != 'pull_request' || !github.event.pull_request.draft - runs-on: ubuntu-22.04 - strategy: - matrix: - dir: [backend, frontend] - include: - - dir: backend - sonar_projectKey: bcgov_nr-compliance-enforcement_backend - token: SONAR_TOKEN_BACKEND - - dir: frontend - sonar_projectKey: bcgov_nr-compliance-enforcement_frontend - token: SONAR_TOKEN_FRONTEND - steps: - - uses: bcgov-nr/action-test-and-analyse@v0.0.2 - with: - commands: | - npm ci - npm run test:cov - dir: ${{ matrix.dir }} - sonar_args: > - -Dsonar.exclusions=**/coverage/**,**/node_modules/** - -Dsonar.organization=bcgov-sonarcloud - -Dsonar.project.monorepo.enabled=true - -Dsonar.projectKey=${{ matrix.sonar_projectKey }} - sonar_project_token: ${{ secrets[matrix.token] }} - trivy: - name: Trivy Security Scan - if: github.event_name != 'pull_request' || !github.event.pull_request.draft - runs-on: ubuntu-22.04 - timeout-minutes: 1 - steps: - - uses: actions/checkout@v4 - - name: Run Trivy vulnerability scanner in repo mode - uses: aquasecurity/trivy-action@0.19.0 - with: - format: "sarif" - output: "trivy-results.sarif" - ignore-unfixed: true - scan-type: "fs" - scanners: "vuln,secret,config" - severity: "CRITICAL,HIGH" - - - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@v2 - with: - sarif_file: "trivy-results.sarif" diff --git a/backend/openshift.deploy.yml b/backend/openshift.deploy.yml deleted file mode 100644 index 436a4ad7d..000000000 --- a/backend/openshift.deploy.yml +++ /dev/null @@ -1,292 +0,0 @@ -apiVersion: template.openshift.io/v1 -kind: Template -labels: - app: ${NAME}-${ZONE} - app.kubernetes.io/part-of: ${NAME}-${ZONE} -parameters: - - name: NAME - description: Module name - value: nr-compliance-enforcement - - name: COMPONENT - description: Component name - value: backend - - name: ZONE - description: Deployment zone, e.g. pr-### or prod - required: true - - name: IMAGE_TAG - description: Image tag to use - value: latest - - name: DOMAIN - value: apps.silver.devops.gov.bc.ca - - name: CPU_REQUEST - value: "20m" - - name: MEMORY_REQUEST - value: "100Mi" - - name: CPU_LIMIT - value: "40m" - - name: MEMORY_LIMIT - value: "200Mi" - - name: MIN_REPLICAS - description: The minimum amount of replicas for the horizontal pod autoscaler. - value: "3" - - name: MAX_REPLICAS - description: The maximum amount of replicas for the horizontal pod autoscaler. - value: "5" - - name: REGISTRY - description: Container registry to import from (internal is image-registry.openshift-image-registry.svc:5000) - value: ghcr.io - - name: PROMOTE - description: Image (namespace/name:tag) to promote/import - value: bcgov/nr-compliance-enforcement/backend:prod - - name: PROMOTE_MIGRATION - description: Image (namespace/name:tag) for migration to promote/import - value: bcgov/nr-compliance-enforcement/database-migrations:test - - name: COMPONENT_DB_MIGRATION - description: Component name for database migrations - value: database-migrations - - name: FLYWAY_LOCATIONS - description: Location of flyway scripts, useful when there's a need to run flyway scripts differently in each environment - -objects: - - apiVersion: v1 - kind: ImageStream - metadata: - labels: - app: ${NAME}-${ZONE} - name: ${NAME}-${ZONE}-${COMPONENT} - spec: - lookupPolicy: - local: false - tags: - - name: ${IMAGE_TAG} - from: - kind: DockerImage - name: ${REGISTRY}/${PROMOTE} - referencePolicy: - type: Local - - apiVersion: v1 - kind: ImageStream - metadata: - labels: - app: ${NAME}-${ZONE} - name: ${NAME}-${ZONE}-${COMPONENT_DB_MIGRATION} - spec: - lookupPolicy: - local: false - tags: - - name: ${IMAGE_TAG} - from: - kind: DockerImage - name: ${REGISTRY}/${PROMOTE_MIGRATION} - referencePolicy: - type: Local - - apiVersion: v1 - kind: DeploymentConfig - metadata: - labels: - app: ${NAME}-${ZONE} - name: ${NAME}-${ZONE}-${COMPONENT} - spec: - replicas: 1 - triggers: - - type: ConfigChange - - type: ImageChange - imageChangeParams: - automatic: true - containerNames: - - ${NAME} - from: - kind: ImageStreamTag - name: ${NAME}-${ZONE}-${COMPONENT}:${IMAGE_TAG} - - type: ImageChange - imageChangeParams: - automatic: true - containerNames: - - ${NAME}-${COMPONENT_DB_MIGRATION} - from: - kind: ImageStreamTag - name: ${NAME}-${ZONE}-${COMPONENT_DB_MIGRATION}:${IMAGE_TAG} - selector: - deploymentconfig: ${NAME}-${ZONE}-${COMPONENT} - strategy: - type: Rolling - template: - metadata: - labels: - app: ${NAME}-${ZONE} - deploymentconfig: ${NAME}-${ZONE}-${COMPONENT} - spec: - containers: - - image: ${NAME}-${ZONE}-${COMPONENT}:${IMAGE_TAG} - imagePullPolicy: Always - name: ${NAME} - env: - - name: NODE_TLS_REJECT_UNAUTHORIZED - value: "0" - - name: POSTGRESQL_HOST - value: ${NAME}-${ZONE}-database - - name: POSTGRESQL_DATABASE - valueFrom: - secretKeyRef: - name: ${NAME}-${ZONE}-database - key: database-name - - name: POSTGRESQL_PASSWORD - valueFrom: - secretKeyRef: - name: ${NAME}-${ZONE}-database - key: database-password - - name: POSTGRESQL_USER - valueFrom: - secretKeyRef: - name: ${NAME}-${ZONE}-database - key: database-user - - name: KEYCLOCK_CLIENT_ID - valueFrom: - secretKeyRef: - name: ceds-backend-oicd - key: keycloak-client-id - - name: JWKS_URI - valueFrom: - secretKeyRef: - name: ceds-backend-oicd - key: jwks-uri - - name: JWT_ISSUER - valueFrom: - secretKeyRef: - name: ceds-backend-oicd - key: jwt-issuer - - name: BC_GEOCODER_API_URL - valueFrom: - secretKeyRef: - name: bc-geo-coder - key: BC_GEOCODER_API_URL - - name: COMPLAINTS_API_KEY - valueFrom: - secretKeyRef: - name: webeoc - key: complaints-api-key - - name: CASE_MANAGEMENT_API_URL - valueFrom: - secretKeyRef: - name: ${NAME}-${ZONE}-case-management - key: case-management-api-url - - name: SEQ_RESET_VALUE - valueFrom: - secretKeyRef: - name: sequence-reset-cron - key: seq-reset-value - - name: SEQ_RESET_CRON_EXPRESSION - valueFrom: - secretKeyRef: - name: sequence-reset-cron - key: seq-reset-cron-expression - - name: COMS_JWT_AUTH_URI - valueFrom: - secretKeyRef: - name: cdogs - key: coms-jwt-auth-uri - - name: CDOGS_URI - valueFrom: - secretKeyRef: - name: cdogs - key: cdogs-uri - - name: CDOGS_CLIENT_ID - valueFrom: - secretKeyRef: - name: cdogs - key: cdogs-client-id - - name: CDOGS_CLIENT_SECRET - valueFrom: - secretKeyRef: - name: cdogs - key: cdogs-client-secret - ports: - - containerPort: 3000 - protocol: TCP - resources: - requests: - cpu: ${CPU_REQUEST} - memory: ${MEMORY_REQUEST} - limits: - cpu: ${CPU_LIMIT} - memory: ${MEMORY_LIMIT} - readinessProbe: - httpGet: - path: /api - port: 3000 - scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 15 - timeoutSeconds: 5 - livenessProbe: - successThreshold: 1 - failureThreshold: 3 - httpGet: - path: /api - port: 3000 - scheme: HTTP - initialDelaySeconds: 60 - periodSeconds: 30 - timeoutSeconds: 5 - initContainers: - - name: ${NAME}-${COMPONENT_DB_MIGRATION} - image: ${NAME}-${ZONE}-${COMPONENT_DB_MIGRATION}:${IMAGE_TAG} - env: - - name: FLYWAY_URL - value: "jdbc:postgresql://${NAME}-${ZONE}-database:5432/${NAME}" - - name: FLYWAY_USER - valueFrom: - secretKeyRef: - name: ${NAME}-${ZONE}-database - key: database-user - - name: FLYWAY_PASSWORD - valueFrom: - secretKeyRef: - name: ${NAME}-${ZONE}-database - key: database-password - - name: FLYWAY_BASELINE_ON_MIGRATE - value: "true" - - name: FLYWAY_LOCATIONS - value: ${FLYWAY_LOCATIONS} - - name: FLYWAY_DEFAULT_SCHEMA - value: "public" - resources: - requests: - cpu: ${CPU_REQUEST} - memory: ${MEMORY_REQUEST} - limits: - cpu: ${CPU_LIMIT} - memory: ${MEMORY_LIMIT} - - apiVersion: v1 - kind: Service - metadata: - labels: - app: ${NAME}-${ZONE} - name: ${NAME}-${ZONE}-${COMPONENT} - spec: - ports: - - name: 3000-tcp - protocol: TCP - port: 80 - targetPort: 3000 - selector: - deploymentconfig: ${NAME}-${ZONE}-${COMPONENT} - - - apiVersion: autoscaling/v2 - kind: HorizontalPodAutoscaler - metadata: - name: ${NAME}-${ZONE}-${COMPONENT} - spec: - scaleTargetRef: - apiVersion: apps.openshift.io/v1 - kind: DeploymentConfig - name: ${NAME}-${ZONE}-${COMPONENT} - minReplicas: ${{MIN_REPLICAS}} - maxReplicas: ${{MAX_REPLICAS}} - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 100 diff --git a/backend/src/auth/jwtauth.guard.ts b/backend/src/auth/jwtauth.guard.ts index 08d80f6ce..6cb771187 100644 --- a/backend/src/auth/jwtauth.guard.ts +++ b/backend/src/auth/jwtauth.guard.ts @@ -29,6 +29,9 @@ export class JwtAuthGuard extends AuthGuard("jwt") { } handleRequest(err, user, info) { if (err || !user) { + this.logger.error( + ` JWKS_URI ${process.env.JWKS_URI} JWT_ISSUER ${process.env.JWT_ISSUER} KEYCLOCK_CLIENT_ID ${process.env.KEYCLOCK_CLIENT_ID}`, + ); this.logger.error(`JWT is not Valid. Err: ${err}. - User ${user}. - Info. ${info}`); throw err || new UnauthorizedException(); } diff --git a/charts/app/.helmignore b/charts/app/.helmignore new file mode 100644 index 000000000..0e8a0eb36 --- /dev/null +++ b/charts/app/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/app/Chart.lock b/charts/app/Chart.lock new file mode 100644 index 000000000..6135759c8 --- /dev/null +++ b/charts/app/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: postgresql + repository: https://charts.bitnami.com/bitnami + version: 15.5.13 +digest: sha256:e29db8b50c7ad4e611c43b4590506d2172ac278b08f015fe0240ba123f2166ec +generated: "2024-07-03T12:48:59.269045601Z" diff --git a/charts/app/Chart.yaml b/charts/app/Chart.yaml new file mode 100644 index 000000000..8662d4109 --- /dev/null +++ b/charts/app/Chart.yaml @@ -0,0 +1,37 @@ +apiVersion: v2 +name: quickstart-openshift +description: A Helm chart for Kubernetes deployment. +icon: https://www.nicepng.com/png/detail/521-5211827_bc-icon-british-columbia-government-logo.png + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" + +dependencies: + - name: postgresql + condition: bitnami-pg.enabled + version: 15.5.13 + repository: https://charts.bitnami.com/bitnami + alias: bitnami-pg +maintainers: + - name: Om Mishra + email: omprakash.2.mishra@gov.bc.ca + - name: Derek Roberts + email: derek.roberts@gov.bc.ca diff --git a/charts/app/README.md b/charts/app/README.md new file mode 100644 index 000000000..9e072a052 --- /dev/null +++ b/charts/app/README.md @@ -0,0 +1,5228 @@ +# quickstart-openshift + +A Helm chart for Kubernetes deployment. + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.16.0](https://img.shields.io/badge/AppVersion-1.16.0-informational?style=flat-square) + +## Maintainers + +| Name | Email | Url | +| ---- | ------ | --- | +| Om Mishra | | | +| Derek Roberts | | | + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| https://bcgov.github.io/helm-service | backend(component) | 0.2.3 | +| https://bcgov.github.io/helm-service | frontend(component) | 0.2.3 | +| https://bcgov.github.io/helm-service | backup(component) | 0.2.3 | +| https://charts.bitnami.com/bitnami | bitnami-pg(postgresql) | 13.2.23 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyTypeDefaultDescription
backend.affinityobject
+{}
+
+
backend.autoscaling.behavior.scaleDown.policies[0].periodSecondsint
+60
+
+
backend.autoscaling.behavior.scaleDown.policies[0].typestring
+"Percent"
+
+
backend.autoscaling.behavior.scaleDown.policies[0].valueint
+10
+
+
backend.autoscaling.behavior.scaleDown.policies[1].periodSecondsint
+60
+
+
backend.autoscaling.behavior.scaleDown.policies[1].typestring
+"Pods"
+
+
backend.autoscaling.behavior.scaleDown.policies[1].valueint
+2
+
+
backend.autoscaling.behavior.scaleDown.selectPolicystring
+"Min"
+
+
backend.autoscaling.behavior.scaleDown.stabilizationWindowSecondsint
+300
+
+
backend.autoscaling.behavior.scaleUp.policies[0].periodSecondsint
+30
+
+
backend.autoscaling.behavior.scaleUp.policies[0].typestring
+"Percent"
+
+
backend.autoscaling.behavior.scaleUp.policies[0].valueint
+100
+
+
backend.autoscaling.behavior.scaleUp.policies[1].periodSecondsint
+30
+
+
backend.autoscaling.behavior.scaleUp.policies[1].typestring
+"Pods"
+
+
backend.autoscaling.behavior.scaleUp.policies[1].valueint
+2
+
+
backend.autoscaling.behavior.scaleUp.selectPolicystring
+"Max"
+
+
backend.autoscaling.behavior.scaleUp.stabilizationWindowSecondsint
+0
+
+
backend.autoscaling.enabledbool
+true
+
+
backend.autoscaling.maxReplicasint
+7
+
+
backend.autoscaling.minReplicasint
+3
+
+
backend.autoscaling.targetCPUUtilizationPercentageint
+80
+
+
backend.containers[0].env.fromGlobalSecret[0].keystring
+"password"
+
+
backend.containers[0].env.fromGlobalSecret[0].namestring
+"POSTGRES_PASSWORD"
+
+
backend.containers[0].env.fromGlobalSecret[1].keystring
+"databaseUser"
+
+
backend.containers[0].env.fromGlobalSecret[1].namestring
+"POSTGRES_USER"
+
+
backend.containers[0].env.fromGlobalSecret[2].keystring
+"databaseName"
+
+
backend.containers[0].env.fromGlobalSecret[2].namestring
+"POSTGRES_DATABASE"
+
+
backend.containers[0].env.fromValues[0].namestring
+"POSTGRES_HOST"
+
+
backend.containers[0].env.fromValues[0].valuestring
+"{{ .Release.Name }}-{{.Values.global.databaseAlias}}"
+
+
backend.containers[0].imagestring
+"backend"
+
+
backend.containers[0].livenessProbe.failureThresholdint
+3
+
+
backend.containers[0].livenessProbe.httpGet.pathstring
+"/api"
+
+
backend.containers[0].livenessProbe.httpGet.portint
+3000
+
+
backend.containers[0].livenessProbe.httpGet.schemestring
+"HTTP"
+
+
backend.containers[0].livenessProbe.initialDelaySecondsint
+15
+
+
backend.containers[0].livenessProbe.periodSecondsint
+30
+
+
backend.containers[0].livenessProbe.successThresholdint
+1
+
+
backend.containers[0].livenessProbe.timeoutSecondsint
+5
+
+
backend.containers[0].namestring
+"backend"
+
+
backend.containers[0].ports[0].containerPortint
+3000
+
+
backend.containers[0].ports[0].namestring
+"http"
+
+
backend.containers[0].ports[0].protocolstring
+"TCP"
+
+
backend.containers[0].readinessProbe.failureThresholdint
+30
+
+
backend.containers[0].readinessProbe.httpGet.pathstring
+"/api"
+
+
backend.containers[0].readinessProbe.httpGet.portint
+3000
+
+
backend.containers[0].readinessProbe.httpGet.schemestring
+"HTTP"
+
+
backend.containers[0].readinessProbe.initialDelaySecondsint
+5
+
+
backend.containers[0].readinessProbe.periodSecondsint
+2
+
+
backend.containers[0].readinessProbe.successThresholdint
+1
+
+
backend.containers[0].readinessProbe.timeoutSecondsint
+2
+
+
backend.containers[0].registrystring
+"{{ .Values.global.registry }}"
+
+
backend.containers[0].repositorystring
+"{{ .Values.global.repository }}"
+
+
backend.containers[0].resources.limits.cpustring
+"250m"
+
+
backend.containers[0].resources.limits.memorystring
+"250Mi"
+
+
backend.containers[0].resources.requests.cpustring
+"100m"
+
+
backend.containers[0].resources.requests.memorystring
+"150Mi"
+
+
backend.containers[0].tagstring
+"{{ .Values.global.tag }}"
+
+
backend.deployment.enabledbool
+true
+
+
backend.deploymentStrategy.typestring
+"Recreate"
+
+
backend.enabledbool
+true
+
+
backend.initContainers[0].env.fromGlobalSecret[0].keystring
+"databasePassword"
+
+
backend.initContainers[0].env.fromGlobalSecret[0].namestring
+"FLYWAY_PASSWORD"
+
+
backend.initContainers[0].env.fromGlobalSecret[1].keystring
+"databaseJDBCURLNoCreds"
+
+
backend.initContainers[0].env.fromGlobalSecret[1].namestring
+"FLYWAY_URL"
+
+
backend.initContainers[0].env.fromGlobalSecret[2].keystring
+"databaseUser"
+
+
backend.initContainers[0].env.fromGlobalSecret[2].namestring
+"FLYWAY_USER"
+
+
backend.initContainers[0].env.fromValues[0].namestring
+"FLYWAY_BASELINE_ON_MIGRATE"
+
+
backend.initContainers[0].env.fromValues[0].valuestring
+"true"
+
+
backend.initContainers[0].env.fromValues[1].namestring
+"FLYWAY_DEFAULT_SCHEMA"
+
+
backend.initContainers[0].env.fromValues[1].valuestring
+"USERS"
+
+
backend.initContainers[0].env.fromValues[2].namestring
+"FLYWAY_CONNECT_RETRIES"
+
+
backend.initContainers[0].env.fromValues[2].valuestring
+"30"
+
+
backend.initContainers[0].imagestring
+"migrations"
+
+
backend.initContainers[0].namestring
+"database-migrations"
+
+
backend.initContainers[0].registrystring
+"{{ .Values.global.registry }}"
+
+
backend.initContainers[0].repositorystring
+"{{ .Values.global.repository }}"
+
+
backend.initContainers[0].resources.limits.cpustring
+"500m"
+
+
backend.initContainers[0].resources.limits.memorystring
+"250Mi"
+
+
backend.initContainers[0].resources.requests.cpustring
+"200m"
+
+
backend.initContainers[0].resources.requests.memorystring
+"150Mi"
+
+
backend.initContainers[0].tagstring
+"{{ .Values.global.tag }}"
+
+
backend.nodeSelectorobject
+{}
+
+
backend.service.enabledbool
+true
+
+
backend.service.ports[0].namestring
+"http"
+
+
backend.service.ports[0].portint
+80
+
+
backend.service.ports[0].protocolstring
+"TCP"
+
+
backend.service.ports[0].targetPortint
+3000
+
+
backend.service.typestring
+"ClusterIP"
+
+
backend.tolerationslist
+[]
+
+
backend.vault.enabledbool
+false
+
+
backend.vault.resources.limits.cpustring
+"50m"
+
+
backend.vault.resources.limits.memorystring
+"50Mi"
+
+
backend.vault.resources.requests.cpustring
+"50m"
+
+
backend.vault.resources.requests.memorystring
+"25Mi"
+
+
backend.vault.rolestring
+null
+
+
backend.vault.secretPaths[0]string
+"dev/api-1"
+
+
backend.vault.secretPaths[1]string
+"dev/api-2"
+
+
backend.vault.secretPaths[2]string
+"test/api-1"
+
+
backend.vault.secretPaths[3]string
+"test/api-2"
+
+
backend.vault.secretPaths[4]string
+"prod/api-1"
+
+
backend.vault.secretPaths[5]string
+"prod/api-2"
+
+
backup.containers[0].command[0]string
+"/bin/bash"
+
+
backup.containers[0].command[1]string
+"-c"
+
+
backup.containers[0].command[2]string
+"/backup.sh -1"
+
+
backup.containers[0].env.fromGlobalSecret[0].keystring
+"password"
+
+
backup.containers[0].env.fromGlobalSecret[0].namestring
+"DATABASE_PASSWORD"
+
+
backup.containers[0].env.fromGlobalSecret[1].keystring
+"databaseName"
+
+
backup.containers[0].env.fromGlobalSecret[1].namestring
+"POSTGRESQL_DATABASE"
+
+
backup.containers[0].env.fromGlobalSecret[2].keystring
+"databaseUser"
+
+
backup.containers[0].env.fromGlobalSecret[2].namestring
+"DATABASE_USER"
+
+
backup.containers[0].env.fromValues[0].namestring
+"BACKUP_DIR"
+
+
backup.containers[0].env.fromValues[0].valuestring
+"/backups/"
+
+
backup.containers[0].env.fromValues[1].namestring
+"BACKUP_STRATEGY"
+
+
backup.containers[0].env.fromValues[1].valuestring
+"rolling"
+
+
backup.containers[0].env.fromValues[2].namestring
+"NUM_BACKUPS"
+
+
backup.containers[0].env.fromValues[2].valuestring
+"5"
+
+
backup.containers[0].env.fromValues[3].namestring
+"DAILY_BACKUPS"
+
+
backup.containers[0].env.fromValues[3].valuestring
+"7"
+
+
backup.containers[0].env.fromValues[4].namestring
+"WEEKLY_BACKUPS"
+
+
backup.containers[0].env.fromValues[4].valuestring
+"4"
+
+
backup.containers[0].env.fromValues[5].namestring
+"MONTHLY_BACKUPS"
+
+
backup.containers[0].env.fromValues[5].valuestring
+"1"
+
+
backup.containers[0].env.fromValues[6].namestring
+"DATABASE_SERVICE_NAME"
+
+
backup.containers[0].env.fromValues[6].valuestring
+"{{.Release.Name}}-{{.Values.global.databaseAlias}}"
+
+
backup.containers[0].env.fromValues[7].namestring
+"DEFAULT_PORT"
+
+
backup.containers[0].env.fromValues[7].valuestring
+"5432"
+
+
backup.containers[0].imagestring
+"backup-container"
+
+
backup.containers[0].namestring
+"backup"
+
+
backup.containers[0].registrystring
+"docker.io"
+
+
backup.containers[0].repositorystring
+"bcgovimages"
+
+
backup.containers[0].resources.limits.cpustring
+"50m"
+
+
backup.containers[0].resources.limits.memorystring
+"256Mi"
+
+
backup.containers[0].resources.requests.cpustring
+"20m"
+
+
backup.containers[0].resources.requests.memorystring
+"128Mi"
+
+
backup.containers[0].tagstring
+"latest"
+
+
backup.containers[0].volumeMounts[0].mountPathstring
+"/backups/"
+
+
backup.containers[0].volumeMounts[0].namestring
+"{{.Release.Name}}-backup"
+
+
backup.cronjob.concurrencyPolicystring
+"Replace"
+
+
backup.cronjob.enabledbool
+true
+
+
backup.cronjob.failedJobsHistoryLimitint
+7
+
+
backup.cronjob.restartPolicystring
+"Never"
+
+
backup.cronjob.schedulestring
+"0 0 * * *"
+
+
backup.cronjob.startingDeadlineSecondsint
+3600
+
+
backup.cronjob.successfulJobsHistoryLimitint
+30
+
+
backup.cronjob.volumes[0].namestring
+"{{.Release.Name}}-backup"
+
+
backup.cronjob.volumes[0].persistentVolumeClaim.claimNamestring
+"{{.Release.Name}}-backup"
+
+
backup.enabledbool
+true
+
+
backup.pvc.accessModesstring
+"ReadWriteOnce"
+
+
backup.pvc.enabledbool
+true
+
+
backup.pvc.sizestring
+"256Mi"
+
+
backup.pvc.storageClassNamestring
+"netapp-file-standard"
+
+
bitnami-pg.auth.databasestring
+"quickstart"
+
+
bitnami-pg.auth.existingSecretstring
+"{{ .Release.Name }}"
+
+
bitnami-pg.auth.usernamestring
+"quickstart"
+
+
bitnami-pg.backup.cronjob.containerSecurityContextobject
+{}
+
+
bitnami-pg.backup.cronjob.podSecurityContext.enabledbool
+false
+
+
bitnami-pg.backup.cronjob.storage.sizestring
+"200Mi"
+
+
bitnami-pg.backup.enabledbool
+false
+
+
bitnami-pg.enabledbool
+true
+
+
bitnami-pg.image.registrystring
+"ghcr.io"
+
+
bitnami-pg.image.repositorystring
+"bcgov/nr-containers/bitnami/postgresql"
+
+
bitnami-pg.image.tagstring
+"15.5.0"
+
+
bitnami-pg.primary.containerSecurityContext.enabledbool
+false
+
+
bitnami-pg.primary.initdb.scripts."postgis.sh"string
+"#!/bin/sh\nPGPASSWORD=$POSTGRES_PASSWORD psql -U postgres -d postgres -c \"CREATE EXTENSION postgis;\"\n"
+
+
bitnami-pg.primary.persistence.accessModes[0]string
+"ReadWriteOnce"
+
+
bitnami-pg.primary.persistence.enabledbool
+true
+
+
bitnami-pg.primary.persistence.sizestring
+"100Mi"
+
+
bitnami-pg.primary.persistence.storageClassstring
+"netapp-file-standard"
+
+
bitnami-pg.primary.podSecurityContext.enabledbool
+false
+
+
bitnami-pg.primary.resources.limits.cpustring
+"150m"
+
+
bitnami-pg.primary.resources.limits.memorystring
+"250Mi"
+
+
bitnami-pg.primary.resources.requests.cpustring
+"50m"
+
+
bitnami-pg.primary.resources.requests.memorystring
+"150Mi"
+
+
bitnami-pg.shmVolume.enabledbool
+false
+
+
crunchy.crunchyImagestring
+"artifacts.developer.gov.bc.ca/bcgov-docker-local/crunchy-postgres-gis:ubi8-15.2-3.3-0"
+
+
crunchy.enabledbool
+false
+
+
crunchy.imagePullPolicystring
+"Always"
+
+
crunchy.instances.dataVolumeClaimSpec.storagestring
+"120Mi"
+
+
crunchy.instances.dataVolumeClaimSpec.storageClassNamestring
+"netapp-block-standard"
+
+
crunchy.instances.limits.cpustring
+"100m"
+
+
crunchy.instances.limits.memorystring
+"512Mi"
+
+
crunchy.instances.metadata.annotations."prometheus.io/port"string
+"9187"
+
+
crunchy.instances.metadata.annotations."prometheus.io/scrape"string
+"true"
+
+
crunchy.instances.namestring
+"ha"
+
+
crunchy.instances.replicaCertCopy.limits.cpustring
+"50m"
+
+
crunchy.instances.replicaCertCopy.limits.memorystring
+"64Mi"
+
+
crunchy.instances.replicaCertCopy.requests.cpustring
+"1m"
+
+
crunchy.instances.replicaCertCopy.requests.memorystring
+"32Mi"
+
+
crunchy.instances.replicasint
+1
+
+
crunchy.instances.requests.cpustring
+"25m"
+
+
crunchy.instances.requests.memorystring
+"256Mi"
+
+
crunchy.patroni.postgresql.parameters.max_slot_wal_keep_sizestring
+"128MB"
+
+
crunchy.patroni.postgresql.parameters.max_wal_sizestring
+"64MB"
+
+
crunchy.patroni.postgresql.parameters.min_wal_sizestring
+"32MB"
+
+
crunchy.patroni.postgresql.parameters.shared_buffersstring
+"16MB"
+
+
crunchy.patroni.postgresql.parameters.wal_buffersstring
+"64kB"
+
+
crunchy.patroni.postgresql.pg_hbastring
+"host all all 0.0.0.0/0 md5"
+
+
crunchy.pgBackRest.enabledbool
+false
+
+
crunchy.pgBackRest.imagestring
+null
+
+
crunchy.pgBackRest.repoHost.limits.cpustring
+"50m"
+
+
crunchy.pgBackRest.repoHost.limits.memorystring
+"128Mi"
+
+
crunchy.pgBackRest.repoHost.requests.cpustring
+"1m"
+
+
crunchy.pgBackRest.repoHost.requests.memorystring
+"64Mi"
+
+
crunchy.pgBackRest.repos.schedules.fullstring
+"0 8 * * *"
+
+
crunchy.pgBackRest.repos.schedules.incrementalstring
+"0 0,4,12,16,20 * * *"
+
+
crunchy.pgBackRest.repos.volume.accessModesstring
+"ReadWriteOnce"
+
+
crunchy.pgBackRest.repos.volume.storagestring
+"64Mi"
+
+
crunchy.pgBackRest.repos.volume.storageClassNamestring
+"netapp-file-backup"
+
+
crunchy.pgBackRest.retentionstring
+"1"
+
+
crunchy.pgBackRest.retentionFullTypestring
+"count"
+
+
crunchy.pgBackRest.sidecars.limits.cpustring
+"50m"
+
+
crunchy.pgBackRest.sidecars.limits.memorystring
+"128Mi"
+
+
crunchy.pgBackRest.sidecars.requests.cpustring
+"1m"
+
+
crunchy.pgBackRest.sidecars.requests.memorystring
+"64Mi"
+
+
crunchy.pgmonitor.enabledbool
+false
+
+
crunchy.pgmonitor.exporter.imagestring
+null
+
+
crunchy.pgmonitor.exporter.limits.cpustring
+"50m"
+
+
crunchy.pgmonitor.exporter.limits.memorystring
+"128Mi"
+
+
crunchy.pgmonitor.exporter.requests.cpustring
+"1m"
+
+
crunchy.pgmonitor.exporter.requests.memorystring
+"64Mi"
+
+
crunchy.postGISVersionstring
+"3.3"
+
+
crunchy.postgresVersionint
+15
+
+
crunchy.proxy.pgBouncer.imagestring
+null
+
+
crunchy.proxy.pgBouncer.limits.cpustring
+"50m"
+
+
crunchy.proxy.pgBouncer.limits.memorystring
+"128Mi"
+
+
crunchy.proxy.pgBouncer.replicasint
+1
+
+
crunchy.proxy.pgBouncer.requests.cpustring
+"1m"
+
+
crunchy.proxy.pgBouncer.requests.memorystring
+"64Mi"
+
+
frontend.autoscaling.behavior.scaleDown.policies[0].periodSecondsint
+60
+
+
frontend.autoscaling.behavior.scaleDown.policies[0].typestring
+"Percent"
+
+
frontend.autoscaling.behavior.scaleDown.policies[0].valueint
+10
+
+
frontend.autoscaling.behavior.scaleDown.policies[1].periodSecondsint
+60
+
+
frontend.autoscaling.behavior.scaleDown.policies[1].typestring
+"Pods"
+
+
frontend.autoscaling.behavior.scaleDown.policies[1].valueint
+2
+
+
frontend.autoscaling.behavior.scaleDown.selectPolicystring
+"Min"
+
+
frontend.autoscaling.behavior.scaleDown.stabilizationWindowSecondsint
+300
+
+
frontend.autoscaling.behavior.scaleUp.policies[0].periodSecondsint
+30
+
+
frontend.autoscaling.behavior.scaleUp.policies[0].typestring
+"Percent"
+
+
frontend.autoscaling.behavior.scaleUp.policies[0].valueint
+100
+
+
frontend.autoscaling.behavior.scaleUp.policies[1].periodSecondsint
+30
+
+
frontend.autoscaling.behavior.scaleUp.policies[1].typestring
+"Pods"
+
+
frontend.autoscaling.behavior.scaleUp.policies[1].valueint
+2
+
+
frontend.autoscaling.behavior.scaleUp.selectPolicystring
+"Max"
+
+
frontend.autoscaling.behavior.scaleUp.stabilizationWindowSecondsint
+0
+
+
frontend.autoscaling.enabledbool
+true
+
+
frontend.autoscaling.maxReplicasint
+7
+
+
frontend.autoscaling.minReplicasint
+3
+
+
frontend.autoscaling.targetCPUUtilizationPercentageint
+80
+
+
frontend.configmapobject
+{
+  "data": {
+    "config.js": "const envConfig = (() =\u003e {\n  return {\n    \"VITE_DEPLOY_ENVIRONMENT\":\"{{ .Release.Name }}-{{ .Release.Namespace }}\"\n  };\n})();",
+    "config.prod.js": "const envConfig = (() =\u003e {\n  return {\n    \"VITE_DEPLOY_ENVIRONMENT\":\"static\"\n  };\n})();"
+  },
+  "enabled": true
+}
+
+
the configmap specific to the component.
frontend.configmap.dataobject
+{
+  "config.js": "const envConfig = (() =\u003e {\n  return {\n    \"VITE_DEPLOY_ENVIRONMENT\":\"{{ .Release.Name }}-{{ .Release.Namespace }}\"\n  };\n})();",
+  "config.prod.js": "const envConfig = (() =\u003e {\n  return {\n    \"VITE_DEPLOY_ENVIRONMENT\":\"static\"\n  };\n})();"
+}
+
+
dat contains key value pairs for the configmap. can contain multiple files. value can be piped as string.
frontend.configmap.enabledbool
+true
+
+
enable or disable the configmap.
frontend.containerslist
+[
+  {
+    "env": {
+      "fromLocalConfigmap": [
+        {
+          "key": "config.js",
+          "name": "frontend-configmap"
+        },
+        {
+          "key": "config.prod.js",
+          "name": "frontend-prod-configmap"
+        }
+      ],
+      "fromValues": [
+        {
+          "name": "BACKEND_URL",
+          "value": "http://{{ .Release.Name }}-backend"
+        },
+        {
+          "name": "LOG_LEVEL",
+          "value": "info"
+        }
+      ]
+    },
+    "image": "frontend",
+    "livenessProbe": {
+      "failureThreshold": 3,
+      "httpGet": {
+        "path": "/health",
+        "port": 3001,
+        "scheme": "HTTP"
+      },
+      "initialDelaySeconds": 15,
+      "periodSeconds": 30,
+      "successThreshold": 1,
+      "timeoutSeconds": 5
+    },
+    "name": "frontend",
+    "ports": [
+      {
+        "containerPort": 3000,
+        "name": "http",
+        "protocol": "TCP"
+      },
+      {
+        "containerPort": 3001,
+        "name": "http2",
+        "protocol": "TCP"
+      }
+    ],
+    "readinessProbe": {
+      "failureThreshold": 30,
+      "httpGet": {
+        "path": "/health",
+        "port": 3001,
+        "scheme": "HTTP"
+      },
+      "initialDelaySeconds": 5,
+      "periodSeconds": 2,
+      "successThreshold": 1,
+      "timeoutSeconds": 2
+    },
+    "registry": "{{ .Values.global.registry }}",
+    "repository": "{{ .Values.global.repository }}",
+    "resources": {
+      "limits": {
+        "cpu": "100m",
+        "memory": "150Mi"
+      },
+      "requests": {
+        "cpu": "30m",
+        "memory": "50Mi"
+      }
+    },
+    "securityContext": {
+      "capabilities": {
+        "add": [
+          "NET_BIND_SERVICE"
+        ]
+      }
+    },
+    "tag": "{{ .Values.global.tag }}"
+  }
+]
+
+
the containers specific to the component. one or many containers can be defined.
frontend.deploymentobject
+{
+  "enabled": true
+}
+
+
can be either a statefulSet or a deployment not both. TBD (StatefulSet)
frontend.deploymentStrategyobject
+{
+  "type": "Recreate"
+}
+
+
the deployment strategy, can be "Recreate" or "RollingUpdate"
frontend.enabledbool
+true
+
+
enable or disable a component deployment.
frontend.route.enabledbool
+true
+
+
frontend.route.hoststring
+"{{ .Release.Name }}-frontend.{{ .Values.global.domain }}"
+
+
frontend.route.targetPortstring
+"http"
+
+
frontend.service.enabledbool
+true
+
+
frontend.service.ports[0].namestring
+"http"
+
+
frontend.service.ports[0].portint
+80
+
+
frontend.service.ports[0].protocolstring
+"TCP"
+
+
frontend.service.ports[0].targetPortint
+3000
+
+
frontend.service.typestring
+"ClusterIP"
+
+
global.autoscalingbool
+true
+
+
global.databaseAliasstring
+"bitnami-pg"
+
+
global.domainstring
+"apps.silver.devops.gov.bc.ca"
+
+
global.openshiftImageRegistrystring
+"image-registry.openshift-image-registry.svc:5000"
+
+
global.podAnnotationsstring
+"app.kubernetes.io/timestamp: {{now | toString }}\n"
+
+
global.registrystring
+"ghcr.io"
+
+
global.repositorystring
+null
+
+
global.secrets.annotation."helm.sh/policy"string
+"keep"
+
+
global.secrets.databaseNamestring
+null
+
+
global.secrets.databasePasswordstring
+null
+
+
global.secrets.databaseUserstring
+null
+
+
global.secrets.enabledbool
+true
+
+
global.tagstring
+null
+
+
+ + +## Values + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyTypeDefaultDescription
backend.affinityobject
+{}
+
+
backend.autoscaling.behavior.scaleDown.policies[0].periodSecondsint
+60
+
+
backend.autoscaling.behavior.scaleDown.policies[0].typestring
+"Percent"
+
+
backend.autoscaling.behavior.scaleDown.policies[0].valueint
+10
+
+
backend.autoscaling.behavior.scaleDown.policies[1].periodSecondsint
+60
+
+
backend.autoscaling.behavior.scaleDown.policies[1].typestring
+"Pods"
+
+
backend.autoscaling.behavior.scaleDown.policies[1].valueint
+2
+
+
backend.autoscaling.behavior.scaleDown.selectPolicystring
+"Min"
+
+
backend.autoscaling.behavior.scaleDown.stabilizationWindowSecondsint
+300
+
+
backend.autoscaling.behavior.scaleUp.policies[0].periodSecondsint
+30
+
+
backend.autoscaling.behavior.scaleUp.policies[0].typestring
+"Percent"
+
+
backend.autoscaling.behavior.scaleUp.policies[0].valueint
+100
+
+
backend.autoscaling.behavior.scaleUp.policies[1].periodSecondsint
+30
+
+
backend.autoscaling.behavior.scaleUp.policies[1].typestring
+"Pods"
+
+
backend.autoscaling.behavior.scaleUp.policies[1].valueint
+2
+
+
backend.autoscaling.behavior.scaleUp.selectPolicystring
+"Max"
+
+
backend.autoscaling.behavior.scaleUp.stabilizationWindowSecondsint
+0
+
+
backend.autoscaling.enabledbool
+true
+
+
backend.autoscaling.maxReplicasint
+7
+
+
backend.autoscaling.minReplicasint
+3
+
+
backend.autoscaling.targetCPUUtilizationPercentageint
+80
+
+
backend.containers[0].env.fromGlobalSecret[0].keystring
+"password"
+
+
backend.containers[0].env.fromGlobalSecret[0].namestring
+"POSTGRES_PASSWORD"
+
+
backend.containers[0].env.fromGlobalSecret[1].keystring
+"databaseUser"
+
+
backend.containers[0].env.fromGlobalSecret[1].namestring
+"POSTGRES_USER"
+
+
backend.containers[0].env.fromGlobalSecret[2].keystring
+"databaseName"
+
+
backend.containers[0].env.fromGlobalSecret[2].namestring
+"POSTGRES_DATABASE"
+
+
backend.containers[0].env.fromValues[0].namestring
+"POSTGRES_HOST"
+
+
backend.containers[0].env.fromValues[0].valuestring
+"{{ .Release.Name }}-{{.Values.global.databaseAlias}}"
+
+
backend.containers[0].imagestring
+"backend"
+
+
backend.containers[0].livenessProbe.failureThresholdint
+3
+
+
backend.containers[0].livenessProbe.httpGet.pathstring
+"/api"
+
+
backend.containers[0].livenessProbe.httpGet.portint
+3000
+
+
backend.containers[0].livenessProbe.httpGet.schemestring
+"HTTP"
+
+
backend.containers[0].livenessProbe.initialDelaySecondsint
+15
+
+
backend.containers[0].livenessProbe.periodSecondsint
+30
+
+
backend.containers[0].livenessProbe.successThresholdint
+1
+
+
backend.containers[0].livenessProbe.timeoutSecondsint
+5
+
+
backend.containers[0].namestring
+"backend"
+
+
backend.containers[0].ports[0].containerPortint
+3000
+
+
backend.containers[0].ports[0].namestring
+"http"
+
+
backend.containers[0].ports[0].protocolstring
+"TCP"
+
+
backend.containers[0].readinessProbe.failureThresholdint
+30
+
+
backend.containers[0].readinessProbe.httpGet.pathstring
+"/api"
+
+
backend.containers[0].readinessProbe.httpGet.portint
+3000
+
+
backend.containers[0].readinessProbe.httpGet.schemestring
+"HTTP"
+
+
backend.containers[0].readinessProbe.initialDelaySecondsint
+5
+
+
backend.containers[0].readinessProbe.periodSecondsint
+2
+
+
backend.containers[0].readinessProbe.successThresholdint
+1
+
+
backend.containers[0].readinessProbe.timeoutSecondsint
+2
+
+
backend.containers[0].registrystring
+"{{ .Values.global.registry }}"
+
+
backend.containers[0].repositorystring
+"{{ .Values.global.repository }}"
+
+
backend.containers[0].resources.limits.cpustring
+"250m"
+
+
backend.containers[0].resources.limits.memorystring
+"250Mi"
+
+
backend.containers[0].resources.requests.cpustring
+"100m"
+
+
backend.containers[0].resources.requests.memorystring
+"150Mi"
+
+
backend.containers[0].tagstring
+"{{ .Values.global.tag }}"
+
+
backend.deployment.enabledbool
+true
+
+
backend.deploymentStrategy.typestring
+"Recreate"
+
+
backend.enabledbool
+true
+
+
backend.initContainers[0].env.fromGlobalSecret[0].keystring
+"databasePassword"
+
+
backend.initContainers[0].env.fromGlobalSecret[0].namestring
+"FLYWAY_PASSWORD"
+
+
backend.initContainers[0].env.fromGlobalSecret[1].keystring
+"databaseJDBCURLNoCreds"
+
+
backend.initContainers[0].env.fromGlobalSecret[1].namestring
+"FLYWAY_URL"
+
+
backend.initContainers[0].env.fromGlobalSecret[2].keystring
+"databaseUser"
+
+
backend.initContainers[0].env.fromGlobalSecret[2].namestring
+"FLYWAY_USER"
+
+
backend.initContainers[0].env.fromValues[0].namestring
+"FLYWAY_BASELINE_ON_MIGRATE"
+
+
backend.initContainers[0].env.fromValues[0].valuestring
+"true"
+
+
backend.initContainers[0].env.fromValues[1].namestring
+"FLYWAY_DEFAULT_SCHEMA"
+
+
backend.initContainers[0].env.fromValues[1].valuestring
+"USERS"
+
+
backend.initContainers[0].env.fromValues[2].namestring
+"FLYWAY_CONNECT_RETRIES"
+
+
backend.initContainers[0].env.fromValues[2].valuestring
+"30"
+
+
backend.initContainers[0].imagestring
+"migrations"
+
+
backend.initContainers[0].namestring
+"database-migrations"
+
+
backend.initContainers[0].registrystring
+"{{ .Values.global.registry }}"
+
+
backend.initContainers[0].repositorystring
+"{{ .Values.global.repository }}"
+
+
backend.initContainers[0].resources.limits.cpustring
+"500m"
+
+
backend.initContainers[0].resources.limits.memorystring
+"250Mi"
+
+
backend.initContainers[0].resources.requests.cpustring
+"200m"
+
+
backend.initContainers[0].resources.requests.memorystring
+"150Mi"
+
+
backend.initContainers[0].tagstring
+"{{ .Values.global.tag }}"
+
+
backend.nodeSelectorobject
+{}
+
+
backend.service.enabledbool
+true
+
+
backend.service.ports[0].namestring
+"http"
+
+
backend.service.ports[0].portint
+80
+
+
backend.service.ports[0].protocolstring
+"TCP"
+
+
backend.service.ports[0].targetPortint
+3000
+
+
backend.service.typestring
+"ClusterIP"
+
+
backend.tolerationslist
+[]
+
+
backend.vault.enabledbool
+false
+
+
backend.vault.resources.limits.cpustring
+"50m"
+
+
backend.vault.resources.limits.memorystring
+"50Mi"
+
+
backend.vault.resources.requests.cpustring
+"50m"
+
+
backend.vault.resources.requests.memorystring
+"25Mi"
+
+
backend.vault.rolestring
+null
+
+
backend.vault.secretPaths[0]string
+"dev/api-1"
+
+
backend.vault.secretPaths[1]string
+"dev/api-2"
+
+
backend.vault.secretPaths[2]string
+"test/api-1"
+
+
backend.vault.secretPaths[3]string
+"test/api-2"
+
+
backend.vault.secretPaths[4]string
+"prod/api-1"
+
+
backend.vault.secretPaths[5]string
+"prod/api-2"
+
+
backup.containers[0].command[0]string
+"/bin/bash"
+
+
backup.containers[0].command[1]string
+"-c"
+
+
backup.containers[0].command[2]string
+"/backup.sh -1"
+
+
backup.containers[0].env.fromGlobalSecret[0].keystring
+"password"
+
+
backup.containers[0].env.fromGlobalSecret[0].namestring
+"DATABASE_PASSWORD"
+
+
backup.containers[0].env.fromGlobalSecret[1].keystring
+"databaseName"
+
+
backup.containers[0].env.fromGlobalSecret[1].namestring
+"POSTGRESQL_DATABASE"
+
+
backup.containers[0].env.fromGlobalSecret[2].keystring
+"databaseUser"
+
+
backup.containers[0].env.fromGlobalSecret[2].namestring
+"DATABASE_USER"
+
+
backup.containers[0].env.fromValues[0].namestring
+"BACKUP_DIR"
+
+
backup.containers[0].env.fromValues[0].valuestring
+"/backups/"
+
+
backup.containers[0].env.fromValues[1].namestring
+"BACKUP_STRATEGY"
+
+
backup.containers[0].env.fromValues[1].valuestring
+"rolling"
+
+
backup.containers[0].env.fromValues[2].namestring
+"NUM_BACKUPS"
+
+
backup.containers[0].env.fromValues[2].valuestring
+"5"
+
+
backup.containers[0].env.fromValues[3].namestring
+"DAILY_BACKUPS"
+
+
backup.containers[0].env.fromValues[3].valuestring
+"7"
+
+
backup.containers[0].env.fromValues[4].namestring
+"WEEKLY_BACKUPS"
+
+
backup.containers[0].env.fromValues[4].valuestring
+"4"
+
+
backup.containers[0].env.fromValues[5].namestring
+"MONTHLY_BACKUPS"
+
+
backup.containers[0].env.fromValues[5].valuestring
+"1"
+
+
backup.containers[0].env.fromValues[6].namestring
+"DATABASE_SERVICE_NAME"
+
+
backup.containers[0].env.fromValues[6].valuestring
+"{{.Release.Name}}-{{.Values.global.databaseAlias}}"
+
+
backup.containers[0].env.fromValues[7].namestring
+"DEFAULT_PORT"
+
+
backup.containers[0].env.fromValues[7].valuestring
+"5432"
+
+
backup.containers[0].imagestring
+"backup-container"
+
+
backup.containers[0].namestring
+"backup"
+
+
backup.containers[0].registrystring
+"docker.io"
+
+
backup.containers[0].repositorystring
+"bcgovimages"
+
+
backup.containers[0].resources.limits.cpustring
+"50m"
+
+
backup.containers[0].resources.limits.memorystring
+"256Mi"
+
+
backup.containers[0].resources.requests.cpustring
+"20m"
+
+
backup.containers[0].resources.requests.memorystring
+"128Mi"
+
+
backup.containers[0].tagstring
+"latest"
+
+
backup.containers[0].volumeMounts[0].mountPathstring
+"/backups/"
+
+
backup.containers[0].volumeMounts[0].namestring
+"{{.Release.Name}}-backup"
+
+
backup.cronjob.concurrencyPolicystring
+"Replace"
+
+
backup.cronjob.enabledbool
+true
+
+
backup.cronjob.failedJobsHistoryLimitint
+7
+
+
backup.cronjob.restartPolicystring
+"Never"
+
+
backup.cronjob.schedulestring
+"0 0 * * *"
+
+
backup.cronjob.startingDeadlineSecondsint
+3600
+
+
backup.cronjob.successfulJobsHistoryLimitint
+30
+
+
backup.cronjob.volumes[0].namestring
+"{{.Release.Name}}-backup"
+
+
backup.cronjob.volumes[0].persistentVolumeClaim.claimNamestring
+"{{.Release.Name}}-backup"
+
+
backup.enabledbool
+true
+
+
backup.pvc.accessModesstring
+"ReadWriteOnce"
+
+
backup.pvc.enabledbool
+true
+
+
backup.pvc.sizestring
+"256Mi"
+
+
backup.pvc.storageClassNamestring
+"netapp-file-standard"
+
+
bitnami-pg.auth.databasestring
+"quickstart"
+
+
bitnami-pg.auth.existingSecretstring
+"{{ .Release.Name }}"
+
+
bitnami-pg.auth.usernamestring
+"quickstart"
+
+
bitnami-pg.backup.cronjob.containerSecurityContextobject
+{}
+
+
bitnami-pg.backup.cronjob.podSecurityContext.enabledbool
+false
+
+
bitnami-pg.backup.cronjob.storage.sizestring
+"200Mi"
+
+
bitnami-pg.backup.enabledbool
+false
+
+
bitnami-pg.enabledbool
+true
+
+
bitnami-pg.image.registrystring
+"ghcr.io"
+
+
bitnami-pg.image.repositorystring
+"bcgov/nr-containers/bitnami/postgresql"
+
+
bitnami-pg.image.tagstring
+"15.5.0"
+
+
bitnami-pg.primary.containerSecurityContext.enabledbool
+false
+
+
bitnami-pg.primary.initdb.scripts."postgis.sh"string
+"#!/bin/sh\nPGPASSWORD=$POSTGRES_PASSWORD psql -U postgres -d postgres -c \"CREATE EXTENSION postgis;\"\n"
+
+
bitnami-pg.primary.persistence.accessModes[0]string
+"ReadWriteOnce"
+
+
bitnami-pg.primary.persistence.enabledbool
+true
+
+
bitnami-pg.primary.persistence.sizestring
+"100Mi"
+
+
bitnami-pg.primary.persistence.storageClassstring
+"netapp-file-standard"
+
+
bitnami-pg.primary.podSecurityContext.enabledbool
+false
+
+
bitnami-pg.primary.resources.limits.cpustring
+"150m"
+
+
bitnami-pg.primary.resources.limits.memorystring
+"250Mi"
+
+
bitnami-pg.primary.resources.requests.cpustring
+"50m"
+
+
bitnami-pg.primary.resources.requests.memorystring
+"150Mi"
+
+
bitnami-pg.shmVolume.enabledbool
+false
+
+
crunchy.crunchyImagestring
+"artifacts.developer.gov.bc.ca/bcgov-docker-local/crunchy-postgres-gis:ubi8-15.2-3.3-0"
+
+
crunchy.enabledbool
+false
+
+
crunchy.imagePullPolicystring
+"Always"
+
+
crunchy.instances.dataVolumeClaimSpec.storagestring
+"120Mi"
+
+
crunchy.instances.dataVolumeClaimSpec.storageClassNamestring
+"netapp-block-standard"
+
+
crunchy.instances.limits.cpustring
+"100m"
+
+
crunchy.instances.limits.memorystring
+"512Mi"
+
+
crunchy.instances.metadata.annotations."prometheus.io/port"string
+"9187"
+
+
crunchy.instances.metadata.annotations."prometheus.io/scrape"string
+"true"
+
+
crunchy.instances.namestring
+"ha"
+
+
crunchy.instances.replicaCertCopy.limits.cpustring
+"50m"
+
+
crunchy.instances.replicaCertCopy.limits.memorystring
+"64Mi"
+
+
crunchy.instances.replicaCertCopy.requests.cpustring
+"1m"
+
+
crunchy.instances.replicaCertCopy.requests.memorystring
+"32Mi"
+
+
crunchy.instances.replicasint
+1
+
+
crunchy.instances.requests.cpustring
+"25m"
+
+
crunchy.instances.requests.memorystring
+"256Mi"
+
+
crunchy.patroni.postgresql.parameters.max_slot_wal_keep_sizestring
+"128MB"
+
+
crunchy.patroni.postgresql.parameters.max_wal_sizestring
+"64MB"
+
+
crunchy.patroni.postgresql.parameters.min_wal_sizestring
+"32MB"
+
+
crunchy.patroni.postgresql.parameters.shared_buffersstring
+"16MB"
+
+
crunchy.patroni.postgresql.parameters.wal_buffersstring
+"64kB"
+
+
crunchy.patroni.postgresql.pg_hbastring
+"host all all 0.0.0.0/0 md5"
+
+
crunchy.pgBackRest.enabledbool
+false
+
+
crunchy.pgBackRest.imagestring
+null
+
+
crunchy.pgBackRest.repoHost.limits.cpustring
+"50m"
+
+
crunchy.pgBackRest.repoHost.limits.memorystring
+"128Mi"
+
+
crunchy.pgBackRest.repoHost.requests.cpustring
+"1m"
+
+
crunchy.pgBackRest.repoHost.requests.memorystring
+"64Mi"
+
+
crunchy.pgBackRest.repos.schedules.fullstring
+"0 8 * * *"
+
+
crunchy.pgBackRest.repos.schedules.incrementalstring
+"0 0,4,12,16,20 * * *"
+
+
crunchy.pgBackRest.repos.volume.accessModesstring
+"ReadWriteOnce"
+
+
crunchy.pgBackRest.repos.volume.storagestring
+"64Mi"
+
+
crunchy.pgBackRest.repos.volume.storageClassNamestring
+"netapp-file-backup"
+
+
crunchy.pgBackRest.retentionstring
+"1"
+
+
crunchy.pgBackRest.retentionFullTypestring
+"count"
+
+
crunchy.pgBackRest.sidecars.limits.cpustring
+"50m"
+
+
crunchy.pgBackRest.sidecars.limits.memorystring
+"128Mi"
+
+
crunchy.pgBackRest.sidecars.requests.cpustring
+"1m"
+
+
crunchy.pgBackRest.sidecars.requests.memorystring
+"64Mi"
+
+
crunchy.pgmonitor.enabledbool
+false
+
+
crunchy.pgmonitor.exporter.imagestring
+null
+
+
crunchy.pgmonitor.exporter.limits.cpustring
+"50m"
+
+
crunchy.pgmonitor.exporter.limits.memorystring
+"128Mi"
+
+
crunchy.pgmonitor.exporter.requests.cpustring
+"1m"
+
+
crunchy.pgmonitor.exporter.requests.memorystring
+"64Mi"
+
+
crunchy.postGISVersionstring
+"3.3"
+
+
crunchy.postgresVersionint
+15
+
+
crunchy.proxy.pgBouncer.imagestring
+null
+
+
crunchy.proxy.pgBouncer.limits.cpustring
+"50m"
+
+
crunchy.proxy.pgBouncer.limits.memorystring
+"128Mi"
+
+
crunchy.proxy.pgBouncer.replicasint
+1
+
+
crunchy.proxy.pgBouncer.requests.cpustring
+"1m"
+
+
crunchy.proxy.pgBouncer.requests.memorystring
+"64Mi"
+
+
frontend.autoscaling.behavior.scaleDown.policies[0].periodSecondsint
+60
+
+
frontend.autoscaling.behavior.scaleDown.policies[0].typestring
+"Percent"
+
+
frontend.autoscaling.behavior.scaleDown.policies[0].valueint
+10
+
+
frontend.autoscaling.behavior.scaleDown.policies[1].periodSecondsint
+60
+
+
frontend.autoscaling.behavior.scaleDown.policies[1].typestring
+"Pods"
+
+
frontend.autoscaling.behavior.scaleDown.policies[1].valueint
+2
+
+
frontend.autoscaling.behavior.scaleDown.selectPolicystring
+"Min"
+
+
frontend.autoscaling.behavior.scaleDown.stabilizationWindowSecondsint
+300
+
+
frontend.autoscaling.behavior.scaleUp.policies[0].periodSecondsint
+30
+
+
frontend.autoscaling.behavior.scaleUp.policies[0].typestring
+"Percent"
+
+
frontend.autoscaling.behavior.scaleUp.policies[0].valueint
+100
+
+
frontend.autoscaling.behavior.scaleUp.policies[1].periodSecondsint
+30
+
+
frontend.autoscaling.behavior.scaleUp.policies[1].typestring
+"Pods"
+
+
frontend.autoscaling.behavior.scaleUp.policies[1].valueint
+2
+
+
frontend.autoscaling.behavior.scaleUp.selectPolicystring
+"Max"
+
+
frontend.autoscaling.behavior.scaleUp.stabilizationWindowSecondsint
+0
+
+
frontend.autoscaling.enabledbool
+true
+
+
frontend.autoscaling.maxReplicasint
+7
+
+
frontend.autoscaling.minReplicasint
+3
+
+
frontend.autoscaling.targetCPUUtilizationPercentageint
+80
+
+
frontend.configmapobject
+{
+  "data": {
+    "config.js": "const envConfig = (() =\u003e {\n  return {\n    \"VITE_DEPLOY_ENVIRONMENT\":\"{{ .Release.Name }}-{{ .Release.Namespace }}\"\n  };\n})();",
+    "config.prod.js": "const envConfig = (() =\u003e {\n  return {\n    \"VITE_DEPLOY_ENVIRONMENT\":\"static\"\n  };\n})();"
+  },
+  "enabled": true
+}
+
+
the configmap specific to the component.
frontend.configmap.dataobject
+{
+  "config.js": "const envConfig = (() =\u003e {\n  return {\n    \"VITE_DEPLOY_ENVIRONMENT\":\"{{ .Release.Name }}-{{ .Release.Namespace }}\"\n  };\n})();",
+  "config.prod.js": "const envConfig = (() =\u003e {\n  return {\n    \"VITE_DEPLOY_ENVIRONMENT\":\"static\"\n  };\n})();"
+}
+
+
dat contains key value pairs for the configmap. can contain multiple files. value can be piped as string.
frontend.configmap.enabledbool
+true
+
+
enable or disable the configmap.
frontend.containerslist
+[
+  {
+    "env": {
+      "fromLocalConfigmap": [
+        {
+          "key": "config.js",
+          "name": "frontend-configmap"
+        },
+        {
+          "key": "config.prod.js",
+          "name": "frontend-prod-configmap"
+        }
+      ],
+      "fromValues": [
+        {
+          "name": "BACKEND_URL",
+          "value": "http://{{ .Release.Name }}-backend"
+        },
+        {
+          "name": "LOG_LEVEL",
+          "value": "info"
+        }
+      ]
+    },
+    "image": "frontend",
+    "livenessProbe": {
+      "failureThreshold": 3,
+      "httpGet": {
+        "path": "/health",
+        "port": 3001,
+        "scheme": "HTTP"
+      },
+      "initialDelaySeconds": 15,
+      "periodSeconds": 30,
+      "successThreshold": 1,
+      "timeoutSeconds": 5
+    },
+    "name": "frontend",
+    "ports": [
+      {
+        "containerPort": 3000,
+        "name": "http",
+        "protocol": "TCP"
+      },
+      {
+        "containerPort": 3001,
+        "name": "http2",
+        "protocol": "TCP"
+      }
+    ],
+    "readinessProbe": {
+      "failureThreshold": 30,
+      "httpGet": {
+        "path": "/health",
+        "port": 3001,
+        "scheme": "HTTP"
+      },
+      "initialDelaySeconds": 5,
+      "periodSeconds": 2,
+      "successThreshold": 1,
+      "timeoutSeconds": 2
+    },
+    "registry": "{{ .Values.global.registry }}",
+    "repository": "{{ .Values.global.repository }}",
+    "resources": {
+      "limits": {
+        "cpu": "100m",
+        "memory": "150Mi"
+      },
+      "requests": {
+        "cpu": "30m",
+        "memory": "50Mi"
+      }
+    },
+    "securityContext": {
+      "capabilities": {
+        "add": [
+          "NET_BIND_SERVICE"
+        ]
+      }
+    },
+    "tag": "{{ .Values.global.tag }}"
+  }
+]
+
+
the containers specific to the component. one or many containers can be defined.
frontend.deploymentobject
+{
+  "enabled": true
+}
+
+
can be either a statefulSet or a deployment not both. TBD (StatefulSet)
frontend.deploymentStrategyobject
+{
+  "type": "Recreate"
+}
+
+
the deployment strategy, can be "Recreate" or "RollingUpdate"
frontend.enabledbool
+true
+
+
enable or disable a component deployment.
frontend.route.enabledbool
+true
+
+
frontend.route.hoststring
+"{{ .Release.Name }}-frontend.{{ .Values.global.domain }}"
+
+
frontend.route.targetPortstring
+"http"
+
+
frontend.service.enabledbool
+true
+
+
frontend.service.ports[0].namestring
+"http"
+
+
frontend.service.ports[0].portint
+80
+
+
frontend.service.ports[0].protocolstring
+"TCP"
+
+
frontend.service.ports[0].targetPortint
+3000
+
+
frontend.service.typestring
+"ClusterIP"
+
+
global.autoscalingbool
+true
+
+
global.databaseAliasstring
+"bitnami-pg"
+
+
global.domainstring
+"apps.silver.devops.gov.bc.ca"
+
+
global.openshiftImageRegistrystring
+"image-registry.openshift-image-registry.svc:5000"
+
+
global.podAnnotationsstring
+"app.kubernetes.io/timestamp: {{now | toString }}\n"
+
+
global.registrystring
+"ghcr.io"
+
+
global.repositorystring
+null
+
+
global.secrets.annotation."helm.sh/policy"string
+"keep"
+
+
global.secrets.databaseNamestring
+null
+
+
global.secrets.databasePasswordstring
+null
+
+
global.secrets.databaseUserstring
+null
+
+
global.secrets.enabledbool
+true
+
+
global.tagstring
+null
+
+
+ + + diff --git a/charts/app/README.md.gotmpl b/charts/app/README.md.gotmpl new file mode 100644 index 000000000..f2720d0f5 --- /dev/null +++ b/charts/app/README.md.gotmpl @@ -0,0 +1,12 @@ +{{ template "chart.header" . }} +{{ template "chart.description" . }} + +{{ template "chart.versionBadge" . }}{{ template "chart.typeBadge" . }}{{ template "chart.appVersionBadge" . }} + +{{ template "chart.maintainersSection" . }} + +{{ template "chart.requirementsSection" . }} + +{{ template "chart.valuesTableHtml" . }} +{{ template "chart.valuesSectionHtml" . }} +{{ template "helm-docs.versionFooter" . }} diff --git a/charts/app/templates/_helpers.tpl b/charts/app/templates/_helpers.tpl new file mode 100644 index 000000000..9462c22c8 --- /dev/null +++ b/charts/app/templates/_helpers.tpl @@ -0,0 +1,47 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s" .Release.Name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "name.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "labels" -}} +helm.sh/chart: {{ include "name.chart" . }} +{{ include "selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "selectorLabels" -}} +app.kubernetes.io/name: {{ include "fullname" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + diff --git a/charts/app/templates/backend/templates/_helpers.tpl b/charts/app/templates/backend/templates/_helpers.tpl new file mode 100644 index 000000000..305a674ad --- /dev/null +++ b/charts/app/templates/backend/templates/_helpers.tpl @@ -0,0 +1,42 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "backend.name" -}} +{{- printf "backend" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "backend.fullname" -}} +{{- $componentName := include "backend.name" . }} +{{- if .Values.backend.fullnameOverride }} +{{- .Values.backend.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $componentName | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "backend.labels" -}} +{{ include "backend.selectorLabels" . }} +{{- if .Values.global.tag }} +app.kubernetes.io/image-version: {{ .Values.global.tag | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/short-name: {{ include "backend.name" . }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "backend.selectorLabels" -}} +app.kubernetes.io/name: {{ include "backend.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + + diff --git a/charts/app/templates/backend/templates/deployment.yaml b/charts/app/templates/backend/templates/deployment.yaml new file mode 100644 index 000000000..022cdddaa --- /dev/null +++ b/charts/app/templates/backend/templates/deployment.yaml @@ -0,0 +1,128 @@ +{{- if .Values.backend.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "backend.fullname" . }} + labels: + {{- include "backend.labels" . | nindent 4 }} +spec: + automountServiceAccountToken: false + strategy: + type: {{ .Values.backend.deploymentStrategy }} + {{- if not .Values.backend.autoscaling.enabled }} + replicas: {{ .Values.backend.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "backend.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + rollme: {{ randAlphaNum 5 | quote }} + prometheus.io/scrape: 'true' + prometheus.io/port: '3000' + prometheus.io/path: '/api/metrics' + labels: + {{- include "backend.labels" . | nindent 8 }} + spec: + automountServiceAccountToken: false + {{- if .Values.backend.podSecurityContext }} + securityContext: + {{- toYaml .Values.backend.podSecurityContext | nindent 12 }} + {{- end }} + initContainers: + - name: {{ include "backend.fullname" . }}-init + image: "{{ .Values.global.registry }}/{{ .Values.global.repository }}/migrations:{{ .Values.global.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ default "Always" .Values.backend.imagePullPolicy }} + envFrom: + - secretRef: + name: {{ .Release.Name }}-flyway + env: + - name: NODE_TLS_REJECT_UNAUTHORIZED + value: "0" + - name: FLYWAY_BASELINE_ON_MIGRATE + value: "true" + - name: FLYWAY_DEFAULT_SCHEMA + value: "public" + - name: FLYWAY_CONNECT_RETRIES + value: "10" + - name: FLYWAY_LOCATIONS + value: "{{- if eq .Release.Namespace "c1c7ed-dev" -}}{{ .Values.global.secrets.flywayLocations.dev }}{{- else if eq .Release.Namespace "c1c7ed-test" -}}{{ .Values.global.secrets.flywayLocations.test }}{{- else if eq .Release.Namespace "c1c7ed-prod" -}}{{ .Values.global.secrets.flywayLocations.prod }}{{- else -}}filesystem:./flyway/sql{{- end }}" + resources: + limits: + cpu: 200m + memory: 200Mi + requests: + cpu: 50m + memory: 100Mi + containers: + - name: {{ include "backend.fullname" . }} + {{- if .Values.backend.securityContext }} + securityContext: + {{- toYaml .Values.backend.securityContext | nindent 12 }} + {{- end }} + image: "{{ .Values.global.registry }}/{{ .Values.global.repository }}/backend:{{ .Values.global.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ default "Always" .Values.backend.imagePullPolicy }} + envFrom: + - secretRef: + name: {{ .Release.Name }}-backend + env: + - name: LOG_LEVEL + value: info + - name: NODE_TLS_REJECT_UNAUTHORIZED + value: "0" + ports: + - name: http + containerPort: {{ .Values.backend.service.targetPort }} + protocol: TCP + readinessProbe: + httpGet: + path: /api + port: http + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 2 + timeoutSeconds: 2 + successThreshold: 1 + failureThreshold: 30 + livenessProbe: + successThreshold: 1 + failureThreshold: 3 + httpGet: + path: /api + port: 3000 + scheme: HTTP + initialDelaySeconds: 15 + periodSeconds: 30 + timeoutSeconds: 5 + resources: # this is optional + limits: + cpu: 150m + memory: 150Mi + requests: + cpu: 50m + memory: 75Mi + {{- with .Values.backend.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.backend.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - {{ include "backend.fullname" . }} + - key: app.kubernetes.io/instance + operator: In + values: + - {{ .Release.Name }} + topologyKey: "kubernetes.io/hostname" + +{{- end }} \ No newline at end of file diff --git a/charts/app/templates/backend/templates/hpa.yaml b/charts/app/templates/backend/templates/hpa.yaml new file mode 100644 index 000000000..d22860931 --- /dev/null +++ b/charts/app/templates/backend/templates/hpa.yaml @@ -0,0 +1,55 @@ +{{- if .Values.global.autoscaling }} +{{- if and .Values.backend.autoscaling .Values.backend.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "backend.fullname" . }} + labels: + {{- include "backend.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "backend.fullname" . }} + minReplicas: {{ .Values.backend.autoscaling.minReplicas }} + maxReplicas: {{ .Values.backend.autoscaling.maxReplicas }} + behavior: + scaleDown: + stabilizationWindowSeconds: 300 + policies: + - type: Percent + value: 10 + periodSeconds: 60 + - type: Pods + value: 2 + periodSeconds: 60 + selectPolicy: Min + scaleUp: + stabilizationWindowSeconds: 0 + policies: + - type: Percent + value: 100 + periodSeconds: 30 + - type: Pods + value: 2 + periodSeconds: 30 + selectPolicy: Max + metrics: + {{- if .Values.backend.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.backend.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.backend.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.backend.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} +{{- end }} diff --git a/charts/app/templates/backend/templates/pdb.yaml b/charts/app/templates/backend/templates/pdb.yaml new file mode 100644 index 000000000..7a22f7b79 --- /dev/null +++ b/charts/app/templates/backend/templates/pdb.yaml @@ -0,0 +1,14 @@ +{{- if and .Values.backend.pdb .Values.backend.pdb.enabled }} +--- +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "backend.fullname" . }} + labels: + {{- include "backend.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "backend.selectorLabels" . | nindent 6 }} + minAvailable: {{ .Values.backend.pdb.minAvailable }} +{{- end }} diff --git a/charts/app/templates/backend/templates/service.yaml b/charts/app/templates/backend/templates/service.yaml new file mode 100644 index 000000000..2ea12d8fb --- /dev/null +++ b/charts/app/templates/backend/templates/service.yaml @@ -0,0 +1,18 @@ +{{- if .Values.backend.enabled }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "backend.fullname" . }} + labels: + {{- include "backend.labels" . | nindent 4 }} +spec: + type: {{ .Values.backend.service.type }} + ports: + - port: {{ .Values.backend.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "backend.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/charts/app/templates/frontend/templates/_helpers.tpl b/charts/app/templates/frontend/templates/_helpers.tpl new file mode 100644 index 000000000..524c972f5 --- /dev/null +++ b/charts/app/templates/frontend/templates/_helpers.tpl @@ -0,0 +1,43 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "frontend.name" -}} +{{- printf "frontend" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "frontend.fullname" -}} +{{- $componentName := include "frontend.name" . }} +{{- if .Values.frontend.fullnameOverride }} +{{- .Values.frontend.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $componentName | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} + + +{{/* +Common labels +*/}} +{{- define "frontend.labels" -}} +{{ include "frontend.selectorLabels" . }} +{{- if .Values.global.tag }} +app.kubernetes.io/image-version: {{ .Values.global.tag | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/short-name: {{ include "frontend.name" . }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "frontend.selectorLabels" -}} +app.kubernetes.io/name: {{ include "frontend.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + + diff --git a/charts/app/templates/frontend/templates/deployment.yaml b/charts/app/templates/frontend/templates/deployment.yaml new file mode 100644 index 000000000..55af3113a --- /dev/null +++ b/charts/app/templates/frontend/templates/deployment.yaml @@ -0,0 +1,120 @@ +{{- if .Values.frontend.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "frontend.fullname" . }} + labels: + {{- include "frontend.labels" . | nindent 4 }} +spec: + automountServiceAccountToken: false + strategy: + type: {{ .Values.frontend.deploymentStrategy }} + {{- if not .Values.frontend.autoscaling.enabled }} + replicas: {{ .Values.frontend.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "frontend.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + rollme: {{ randAlphaNum 5 | quote }} + prometheus.io/scrape: 'true' + prometheus.io/port: '3003' + prometheus.io/path: '/metrics' + labels: + {{- include "frontend.labels" . | nindent 8 }} + spec: + automountServiceAccountToken: false + {{- if .Values.frontend.podSecurityContext }} + securityContext: + {{- toYaml .Values.frontend.podSecurityContext | nindent 12 }} + {{- end }} + containers: + - name: {{ include "frontend.fullname" . }} + securityContext: + capabilities: + add: [ "NET_BIND_SERVICE" ] + image: "{{.Values.global.registry}}/{{.Values.global.repository}}/frontend:{{ .Values.global.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ default "Always" .Values.frontend.imagePullPolicy }} + env: + - name: NODE_TLS_REJECT_UNAUTHORIZED + value: "0" + - name: BACKEND_URL + value: "http://{{ .Release.Name }}-backend" + - name: LOG_LEVEL + value: "info" + - name: KEYCLOAK_URL + valueFrom: + secretKeyRef: + name: react-app + key: keycloak-url + - name: COMS_URL + valueFrom: + secretKeyRef: + name: react-app + key: coms-url + - name: COMS_BUCKET + valueFrom: + secretKeyRef: + name: react-app + key: coms-bucket + - name: SHOW_EXPERIMENTAL_FEATURES + valueFrom: + secretKeyRef: + name: react-app + key: show-experimental-features + - name: ENVIRONMENT_NAME + valueFrom: + secretKeyRef: + name: react-app + key: environment-name + + ports: + - name: http + containerPort: 3000 + protocol: TCP + readinessProbe: + httpGet: + path: /health + port: 3001 + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 2 + timeoutSeconds: 2 + successThreshold: 1 + failureThreshold: 30 + #-- the liveness probe for the container. it is optional and is an object. for default values check this link: https://github.com/bcgov/helm-service/blob/main/charts/component/templates/deployment.yaml#L324-L328 + livenessProbe: + successThreshold: 1 + failureThreshold: 3 + httpGet: + path: /health + port: 3001 + scheme: HTTP + initialDelaySeconds: 15 + periodSeconds: 30 + timeoutSeconds: 5 + resources: + limits: + cpu: 100m + memory: 150Mi + requests: + cpu: 30m + memory: 50Mi + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - {{ include "frontend.fullname" . }} + - key: app.kubernetes.io/instance + operator: In + values: + - {{ .Release.Name }} + topologyKey: "kubernetes.io/hostname" + +{{- end }} diff --git a/charts/app/templates/frontend/templates/hpa.yaml b/charts/app/templates/frontend/templates/hpa.yaml new file mode 100644 index 000000000..94191d14a --- /dev/null +++ b/charts/app/templates/frontend/templates/hpa.yaml @@ -0,0 +1,55 @@ +{{- if .Values.global.autoscaling }} +{{- if and .Values.frontend.autoscaling .Values.frontend.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "frontend.fullname" . }} + labels: + {{- include "frontend.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "frontend.fullname" . }} + minReplicas: {{ .Values.frontend.autoscaling.minReplicas }} + maxReplicas: {{ .Values.frontend.autoscaling.maxReplicas }} + behavior: + scaleDown: + stabilizationWindowSeconds: 300 + policies: + - type: Percent + value: 10 + periodSeconds: 60 + - type: Pods + value: 2 + periodSeconds: 60 + selectPolicy: Min + scaleUp: + stabilizationWindowSeconds: 0 + policies: + - type: Percent + value: 100 + periodSeconds: 30 + - type: Pods + value: 2 + periodSeconds: 30 + selectPolicy: Max + metrics: + {{- if .Values.frontend.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.frontend.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.frontend.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.frontend.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} +{{- end }} diff --git a/charts/app/templates/frontend/templates/ingress.yaml b/charts/app/templates/frontend/templates/ingress.yaml new file mode 100644 index 000000000..43ddd6adf --- /dev/null +++ b/charts/app/templates/frontend/templates/ingress.yaml @@ -0,0 +1,27 @@ +{{- if .Values.frontend.enabled }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "frontend.fullname" . }} + labels: + {{- include "frontend.labels" . | nindent 4 }} + {{- if and .Values.frontend.ingress .Values.frontend.ingress.annotations }} + {{- with .Values.frontend.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} +spec: + ingressClassName: openshift-default + rules: + - host: {{ include "frontend.fullname" . }}.{{ .Values.global.domain }} + http: + paths: + - path: / + pathType: ImplementationSpecific + backend: + service: + name: {{ include "frontend.fullname" . }} + port: + number: 80 +{{- end }} diff --git a/charts/app/templates/frontend/templates/pdb.yaml b/charts/app/templates/frontend/templates/pdb.yaml new file mode 100644 index 000000000..b7067bf58 --- /dev/null +++ b/charts/app/templates/frontend/templates/pdb.yaml @@ -0,0 +1,14 @@ +{{- if and .Values.frontend.pdb .Values.frontend.pdb.enabled }} +--- +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "frontend.fullname" . }} + labels: + {{- include "frontend.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "frontend.selectorLabels" . | nindent 6 }} + minAvailable: {{ .Values.frontend.pdb.minAvailable }} +{{- end }} diff --git a/charts/app/templates/frontend/templates/service.yaml b/charts/app/templates/frontend/templates/service.yaml new file mode 100644 index 000000000..4ba07f696 --- /dev/null +++ b/charts/app/templates/frontend/templates/service.yaml @@ -0,0 +1,25 @@ +{{- if .Values.frontend.enabled }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "frontend.fullname" . }} + labels: + {{- include "frontend.labels" . | nindent 4 }} +spec: + type: {{ .Values.frontend.service.type }} + ports: + - name: http + #-- the port for the service. the service will be accessible on this port within the namespace. + port: 80 + #-- the container port where the application is listening on + targetPort: 3000 + #-- the protocol for the port. it can be TCP or UDP. TCP is the default and is recommended. + protocol: TCP + - port: 3003 + targetPort: 3003 + protocol: TCP + name: metrics + selector: + {{- include "frontend.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/charts/app/templates/knp.yaml b/charts/app/templates/knp.yaml new file mode 100644 index 000000000..6858889b8 --- /dev/null +++ b/charts/app/templates/knp.yaml @@ -0,0 +1,63 @@ +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ .Release.Name }}-openshift-ingress-to-frontend + labels: {{- include "selectorLabels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: frontend + app.kubernetes.io/instance: {{ .Release.Name }} + ingress: + - from: + - namespaceSelector: + matchLabels: + network.openshift.io/policy-group: ingress + policyTypes: + - Ingress +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ .Release.Name }}-allow-backend-to-db + labels: {{- include "selectorLabels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: {{ .Values.global.databaseAlias}} + app.kubernetes.io/instance: {{ .Release.Name }} + ingress: + - ports: + - protocol: TCP + port: 5432 + from: + - podSelector: + matchLabels: + app.kubernetes.io/name: backend + app.kubernetes.io/instance: {{ .Release.Name }} + policyTypes: + - Ingress + +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ .Release.Name }}-allow-frontend-to-backend + labels: {{- include "selectorLabels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: backend + app.kubernetes.io/instance: {{ .Release.Name }} + ingress: + - ports: + - protocol: TCP + port: 3000 + from: + - podSelector: + matchLabels: + app.kubernetes.io/name: frontend + app.kubernetes.io/instance: {{ .Release.Name }} + policyTypes: + - Ingress diff --git a/charts/app/templates/secret.yaml b/charts/app/templates/secret.yaml new file mode 100644 index 000000000..8aab4a1a0 --- /dev/null +++ b/charts/app/templates/secret.yaml @@ -0,0 +1,139 @@ +{{- if and .Values.global.secrets .Values.global.secrets.enabled }} +{{- $databaseUser := .Values.global.secrets.databaseUser | default "postgres" }} +{{- $databasePassword := .Values.global.secrets.databasePassword | default (randAlphaNum 10) }} +{{- $caseManagementApiKey := .Values.global.secrets.caseManagementApiKey | default (randAlphaNum 10) }} +{{- $secretObj := (lookup "v1" "Secret" .Release.Namespace "nr-compliance-enforcement") | default dict }} +{{- $secretData := (get $secretObj "data") | default dict }} + +# Set databasePassword to existing secret data or generate a random one when not exists +{{- $databasePassword = (get $secretData "databasePassword" | default ($databasePassword | b64enc)) }} +{{- $databaseName := .Values.global.secrets.databaseName | default "postgres" }} +{{- $host := printf "%s-%s:5432" .Release.Name .Values.global.databaseAlias }} +{{- $hostWithoutPort := printf "%s-%s" .Release.Name .Values.global.databaseAlias }} +{{- $databaseURL := printf "postgresql://%s:%s@%s/%s" $databaseUser (b64dec $databasePassword) $host $databaseName }} +{{- $databaseJDBCURL := printf "jdbc:postgresql://%s:%s@%s/%s" $databaseUser (b64dec $databasePassword) $host $databaseName }} +{{- $databaseJDBCURLNoCreds := printf "jdbc:postgresql://%s/%s" $host $databaseName }} + +{{- $bcGeocoderApiClientId := (get $secretData "bcGeocoderApiClientId" | b64dec | default (randAlphaNum 10)) }} +{{- $bcGeocoderApiKey := (get $secretData "bcGeocoderApiKey" | b64dec | default (randAlphaNum 10)) }} +{{- $bcGeocoderApiUrl := (get $secretData "bcGeocoderApiUrl" | b64dec | default "") }} +{{- $comsJwtAuthUri := (get $secretData "comsJwtAuthUri" | b64dec | default "") }} +{{- $cdogsUri := (get $secretData "cdogsUri" | b64dec | default "") }} +{{- $cdogsClientId := (get $secretData "cdogsClientId" | b64dec | default "") }} +{{- $cdogsClientSecret := (get $secretData "cdogsClientSecret" | b64dec | default "") }} +{{- $webeocUsername := (get $secretData "webeocUsername" | b64dec | default "") }} +{{- $webeocPassword := (get $secretData "webeocPassword" | b64dec | default "") }} +{{- $webeocPosition := (get $secretData "webeocPosition" | b64dec | default "") }} +{{- $webeocIncident := (get $secretData "webeocIncident" | b64dec | default "") }} +{{- $webeocUrl := (get $secretData "webeocUrl" | b64dec | default "") }} +{{- $webeocComplaintHistorySeconds := (get $secretData "webeocComplaintHistorySeconds" | b64dec | default "") }} +{{- $webeocCronExpression := (get $secretData "webeocCronExpression" | b64dec | default "") }} +{{- $backupDir := (get $secretData "backupDir" | b64dec | default "") }} +{{- $backupStrategy := (get $secretData "backupStrategy" | b64dec | default "") }} +{{- $numBackups := (get $secretData "numBackups" | b64dec | default "") }} +{{- $dailyBackups := (get $secretData "dailyBackups" | b64dec | default "") }} +{{- $weeklyBackups := (get $secretData "weeklyBackups" | b64dec | default "") }} +{{- $monthlyBackups := (get $secretData "monthlyBackups" | b64dec | default "") }} +{{- $databaseServiceName := (get $secretData "databaseServiceName" | b64dec | default "") }} +{{- $objectstoreAccessKey := (get $secretData "objectstoreAccessKey" | b64dec | default "") }} +{{- $objectstoreUrl := (get $secretData "objectstoreUrl" | b64dec | default "") }} +{{- $objectstoreBackupDirectory := (get $secretData "objectstoreBackupDirectory" | b64dec | default "") }} +{{- $objectstoreBucket := (get $secretData "objectstoreBucket" | b64dec | default "") }} +{{- $objectstoreSecretKey := (get $secretData "objectstoreSecretKey" | b64dec | default "") }} +{{- $jwksUri := (get $secretData "jwksUri" | b64dec | default "") }} +{{- $jwtIssuer := (get $secretData "jwtIssuer" | b64dec | default "") }} +{{- $keycloakClientId := (get $secretData "keycloakClientId" | b64dec | default "") }} +{{- $caseManagementApiUrl := (get $secretData "caseManagementApiUrl" | b64dec | default "") }} + + +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-backend + labels: {{- include "labels" . | nindent 4 }} + {{- if .Values.global.secrets.persist }} + annotations: + helm.sh/resource-policy: keep + {{- end }} +data: + # BACKEND Secrets + POSTGRESQL_PASSWORD: {{ $databasePassword | quote }} + POSTGRESQL_USER: {{ $databaseUser | b64enc | quote }} + POSTGRESQL_DATABASE: {{ $databaseName | b64enc | quote }} + POSTGRESQL_HOST: {{ $hostWithoutPort | b64enc | quote }} + JWKS_URI: {{ $jwksUri | b64enc | quote }} + JWT_ISSUER: {{ $jwtIssuer | b64enc | quote }} + KEYCLOCK_CLIENT_ID: {{ $keycloakClientId | b64enc | quote }} + BC_GEOCODER_API_CLIENT_ID: {{ $bcGeocoderApiClientId | b64enc | quote }} + BC_GEOCODER_API_KEY: {{ $bcGeocoderApiKey | b64enc | quote }} + BC_GEOCODER_API_URL: {{ $bcGeocoderApiUrl | b64enc | quote }} + CASE_MANAGEMENT_API_URL: {{ $caseManagementApiUrl | b64enc | quote }} + COMPLAINTS_API_KEY: {{ $caseManagementApiKey | b64enc | quote }} + POSTGRESQL_ENABLE_LOGGING: {{ .Values.global.secrets.postgresqlEnableLogging | b64enc }} + COMS_JWT_AUTH_URI: {{ $comsJwtAuthUri | b64enc | quote }} + CDOGS_URI: {{ $cdogsUri | b64enc | quote }} + CDOGS_CLIENT_ID: {{ $cdogsClientId | b64enc | quote }} + CDOGS_CLIENT_SECRET: {{ $cdogsClientSecret | b64enc | quote }} + # BACKUP Secrets + BACKUP_DIR: {{ $backupDir | b64enc | quote }} + BACKUP_STRATEGY: {{ $backupStrategy | b64enc | quote }} + NUM_BACKUPS: {{ $numBackups | b64enc | quote }} + DAILY_BACKUPS: {{ $dailyBackups | b64enc | quote }} + WEEKLY_BACKUPS: {{ $weeklyBackups | b64enc | quote }} + MONTHLY_BACKUPS: {{ $monthlyBackups | b64enc | quote }} + DATABASE_SERVICE_NAME: {{ $databaseServiceName | b64enc | quote }} + OBJECTSTORE_ACCESS_KEY: {{ $objectstoreAccessKey | b64enc | quote }} + OBJECTSTORE_URL: {{ $objectstoreUrl | b64enc | quote }} + OBJECTSTORE_BACKUP_DIRECTORY: {{ $objectstoreBackupDirectory | b64enc | quote }} + OBJECTSTORE_BUCKET: {{ $objectstoreBucket | b64enc | quote }} + OBJECTSTORE_SECRET_KEY: {{ $objectstoreSecretKey | b64enc | quote }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-webeoc + labels: {{- include "labels" . | nindent 4 }} + {{- if .Values.global.secrets.persist }} + annotations: + helm.sh/resource-policy: keep + {{- end }} +data: + # WEBEOC Secrets + WEBEOC_USERNAME: {{ $webeocUsername | b64enc | quote }} + WEBEOC_PASSWORD: {{ $webeocPassword | b64enc | quote }} + WEBEOC_POSITION: {{ $webeocPosition | b64enc | quote }} + WEBEOC_INCIDENT: {{ $webeocIncident | b64enc | quote }} + WEBEOC_URL: {{ $webeocUrl | b64enc | quote }} + WEBEOC_COMPLAINT_HISTORY_SECONDS: {{ $webeocComplaintHistorySeconds | b64enc | quote }} + WEBEOC_CRON_EXPRESSION: {{ $webeocCronExpression | b64enc | quote }} + COMPLAINTS_API_KEY: {{ $caseManagementApiKey | b64enc | quote }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-flyway + labels: {{- include "labels" . | nindent 4 }} + {{- if .Values.global.secrets.persist }} + annotations: + helm.sh/resource-policy: keep + {{- end }} +data: + FLYWAY_URL: {{ $databaseJDBCURLNoCreds | b64enc | quote }} + FLYWAY_USER: {{ $databaseUser | b64enc | quote }} + FLYWAY_PASSWORD: {{ $databasePassword | quote }} + +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-database + labels: {{- include "labels" . | nindent 4 }} + {{- if .Values.global.secrets.persist }} + annotations: + helm.sh/resource-policy: keep + {{- end }} +data: + postgres-password: {{ $databasePassword | quote }} + password: {{ $databasePassword | quote }} +{{- end }} diff --git a/charts/app/templates/webeoc/templates/_helpers.tpl b/charts/app/templates/webeoc/templates/_helpers.tpl new file mode 100644 index 000000000..37ead8fdd --- /dev/null +++ b/charts/app/templates/webeoc/templates/_helpers.tpl @@ -0,0 +1,42 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "webeoc.name" -}} +{{- printf "webeoc" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "webeoc.fullname" -}} +{{- $componentName := include "webeoc.name" . }} +{{- if .Values.webeoc.fullnameOverride }} +{{- .Values.webeoc.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $componentName | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "webeoc.labels" -}} +{{ include "webeoc.selectorLabels" . }} +{{- if .Values.global.tag }} +app.kubernetes.io/image-version: {{ .Values.global.tag | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/short-name: {{ include "webeoc.name" . }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "webeoc.selectorLabels" -}} +app.kubernetes.io/name: {{ include "webeoc.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + + diff --git a/charts/app/templates/webeoc/templates/deployment.yaml b/charts/app/templates/webeoc/templates/deployment.yaml new file mode 100644 index 000000000..489c657bf --- /dev/null +++ b/charts/app/templates/webeoc/templates/deployment.yaml @@ -0,0 +1,108 @@ +{{- if .Values.webeoc.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "webeoc.fullname" . }} + labels: + {{- include "webeoc.labels" . | nindent 4 }} +spec: + automountServiceAccountToken: false + strategy: + type: {{ .Values.webeoc.deploymentStrategy }} + {{- if not .Values.webeoc.autoscaling.enabled }} + replicas: {{ .Values.webeoc.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "webeoc.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + rollme: {{ randAlphaNum 5 | quote }} + labels: + {{- include "webeoc.labels" . | nindent 8 }} + spec: + automountServiceAccountToken: false + {{- if .Values.webeoc.podSecurityContext }} + securityContext: + {{- toYaml .Values.webeoc.podSecurityContext | nindent 12 }} + {{- end }} + containers: + - name: {{ include "webeoc.fullname" . }} + {{- if .Values.webeoc.securityContext }} + securityContext: + {{- toYaml .Values.webeoc.securityContext | nindent 12 }} + {{- end }} + image: "{{.Values.global.registry}}/{{.Values.global.repository}}/webeoc:{{ .Values.global.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ default "Always" .Values.webeoc.imagePullPolicy }} + envFrom: + - secretRef: + name: {{.Release.Name}}-webeoc + env: + - name: LOG_LEVEL + value: info + - name: NODE_TLS_REJECT_UNAUTHORIZED + value: "0" + - name: NATS_HOST + value: nats://{{.Release.Name}}-nats:4222 + - name: COMPLAINTS_MANAGEMENT_API_URL + value: https://{{.Release.Name}}-frontend.apps.silver.devops.gov.bc.ca/api/v1 + ports: + - name: http + containerPort: {{ .Values.webeoc.service.targetPort }} + protocol: TCP + readinessProbe: + exec: + command: + - /usr/bin/env + - bash + - -c + - ls + initialDelaySeconds: 5 + periodSeconds: 2 + timeoutSeconds: 2 + successThreshold: 1 + failureThreshold: 30 + livenessProbe: + successThreshold: 1 + failureThreshold: 3 + exec: + command: + - /usr/bin/env + - bash + - -c + - ls + initialDelaySeconds: 15 + periodSeconds: 30 + timeoutSeconds: 5 + resources: # this is optional + limits: + cpu: 80m + memory: 150Mi + requests: + cpu: 40m + memory: 75Mi + {{- with .Values.webeoc.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.webeoc.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - {{ include "webeoc.fullname" . }} + - key: app.kubernetes.io/instance + operator: In + values: + - {{ .Release.Name }} + topologyKey: "kubernetes.io/hostname" + +{{- end }} diff --git a/charts/app/templates/webeoc/templates/hpa.yaml b/charts/app/templates/webeoc/templates/hpa.yaml new file mode 100644 index 000000000..fe9bb890d --- /dev/null +++ b/charts/app/templates/webeoc/templates/hpa.yaml @@ -0,0 +1,55 @@ +{{- if .Values.global.autoscaling }} +{{- if and .Values.webeoc.autoscaling .Values.webeoc.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "webeoc.fullname" . }} + labels: + {{- include "webeoc.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "webeoc.fullname" . }} + minReplicas: {{ .Values.webeoc.autoscaling.minReplicas }} + maxReplicas: {{ .Values.webeoc.autoscaling.maxReplicas }} + behavior: + scaleDown: + stabilizationWindowSeconds: 300 + policies: + - type: Percent + value: 10 + periodSeconds: 60 + - type: Pods + value: 2 + periodSeconds: 60 + selectPolicy: Min + scaleUp: + stabilizationWindowSeconds: 0 + policies: + - type: Percent + value: 100 + periodSeconds: 30 + - type: Pods + value: 2 + periodSeconds: 30 + selectPolicy: Max + metrics: + {{- if .Values.webeoc.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.webeoc.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.webeoc.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.webeoc.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} +{{- end }} diff --git a/charts/app/templates/webeoc/templates/service.yaml b/charts/app/templates/webeoc/templates/service.yaml new file mode 100644 index 000000000..612dfb882 --- /dev/null +++ b/charts/app/templates/webeoc/templates/service.yaml @@ -0,0 +1,18 @@ +{{- if .Values.webeoc.enabled }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "webeoc.fullname" . }} + labels: + {{- include "webeoc.labels" . | nindent 4 }} +spec: + type: {{ .Values.webeoc.service.type }} + ports: + - port: {{ .Values.webeoc.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "webeoc.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/charts/app/values.yaml b/charts/app/values.yaml new file mode 100644 index 000000000..94ef7f62f --- /dev/null +++ b/charts/app/values.yaml @@ -0,0 +1,378 @@ +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +#-- global variables, can be accessed by sub-charts. +global: + #-- the registry where the images are stored. override during runtime for other registry at global level or individual level. + repository: bcgov/nr-compliance-enforcement # provide the repo name from where images will be sourced for example bcgo + #-- the registry where the images are stored. override during runtime for other registry at global level or individual level. default is ghcr.io + registry: ghcr.io # ghcr.io for directly streaming from github container registry or "artifacts.developer.gov.bc.ca/github-docker-remote" for artifactory, or any other registry. + #-- the tag of the image, it can be latest, 1.0.0 etc..., or the sha256 hash + tag: ~ + #-- turn off autoscaling for the entire suite by setting this to false. default is true. + autoscaling: false + #-- global secrets, can be accessed by sub-charts. + secrets: + enabled: true + databasePassword: ~ + databaseUser: ~ + databaseName: ~ + persist: true + bcGeocoderApiClientId: ~ + bcGeocoderApiKey: ~ + bcGeocoderApiUrl: ~ + comsJwtAuthUri: ~ + cdogsUri: ~ + cdogsClientId: ~ + cdogsClientSecret: ~ + webeocUsername: ~ + webeocPassword: ~ + webeocPosition: ~ + webeocIncident: ~ + webeocUrl: ~ + webeocComplaintHistorySeconds: ~ + webeocCronExpression: ~ + backupDir: ~ + backupStrategy: ~ + numBackups: ~ + dailyBackups: ~ + weeklyBackups: ~ + monthlyBackups: ~ + databaseServiceName: ~ + objectstoreAccessKey: ~ + objectstoreUrl: ~ + objectstoreBackupDirectory: ~ + objectstoreBucket: ~ + objectstoreSecretKey: ~ + jwksUri: ~ + jwtIssuer: ~ + keycloakClientId: ~ + caseManagementApiUrl: ~ + postgresqlEnableLogging: "false" + flywayLocations: + dev: "filesystem:/flyway/sql, filesystem:/flyway/sql-test" + test: "filesystem:/flyway/sql, filesystem:/flyway/sql-test" + prod: "filesystem:/flyway/sql" + + #-- domain of the application, it is required, apps.silver.devops.gov.bc.ca for silver cluster and apps.devops.gov.bc.ca for gold cluster + domain: "apps.silver.devops.gov.bc.ca" # it is apps.gold.devops.gov.bc.ca for gold cluster + #-- the database Alias gives a nice way to switch to different databases, crunchy, patroni ... etc. + databaseAlias: bitnami-pg + +#-- the components of the application, backend. +backend: + #-- enable or disable backend + enabled: true + #-- the deployment strategy, can be "Recreate" or "RollingUpdate" + deploymentStrategy: Recreate + #-- autoscaling for the component. it is optional and is an object. + autoscaling: + #-- enable or disable autoscaling. + enabled: true + #-- the minimum number of replicas. + minReplicas: 3 + #-- the maximum number of replicas. + maxReplicas: 7 + #-- the target cpu utilization percentage, is from request cpu and NOT LIMIT CPU. + targetCPUUtilizationPercentage: 80 + #-- vault, for injecting secrets from vault. it is optional and is an object. it creates an initContainer which reads from vault and app container can source those secrets. for referring to a working example with vault follow this link: https://github.com/bcgov/onroutebc/blob/main/charts/onroutebc/values.yaml#L171-L186 + vault: + #-- enable or disable vault. + enabled: false + #-- the role of the vault. it is required, #licenseplate-prod or licenseplate-nonprod, license plate is the namespace without env + role: ~ + #-- the vault path where the secrets live. it is required, dev/api-1, dev/api-2, test/api-1 etc... + secretPaths: + - dev/api-1 + - dev/api-2 + - test/api-1 + - test/api-2 + - prod/api-1 + - prod/api-2 + #-- resources specific to vault initContainer. it is optional and is an object. + resources: + limits: + cpu: 50m + memory: 50Mi + requests: + cpu: 50m + memory: 25Mi + #-- the service for the component. for inter namespace communication, use the service name as the hostname. + service: + #-- the type of the service. it can be ClusterIP, NodePort, LoadBalancer, ExternalName. ClusterIP is the default and is recommended. + type: ClusterIP + port: 80 # this is the service port, where it will be exposed internal to the namespace. + targetPort: 3000 # this is container port where app listens on + pdb: + enabled: false # enable it in PRODUCTION for having pod disruption budget. + minAvailable: 1 # the minimum number of pods that must be available during the disruption budget. + +frontend: + # -- enable or disable a component deployment. + enabled: true + # -- the deployment strategy, can be "Recreate" or "RollingUpdate" + deploymentStrategy: Recreate + + #-- autoscaling for the component. it is optional and is an object. + autoscaling: + #-- enable or disable autoscaling. + enabled: true + #-- the minimum number of replicas. + minReplicas: 3 + #-- the maximum number of replicas. + maxReplicas: 7 + #-- the target cpu utilization percentage, is from request cpu and NOT LIMIT CPU. + targetCPUUtilizationPercentage: 80 + #-- the service for the component. for inter namespace communication, use the service name as the hostname. + service: + #-- enable or disable the service. + enabled: true + #-- the type of the service. it can be ClusterIP, NodePort, LoadBalancer, ExternalName. ClusterIP is the default and is recommended. + type: ClusterIP + #-- the ports for the service. + ports: + - name: http + #-- the port for the service. the service will be accessible on this port within the namespace. + port: 80 + #-- the container port where the application is listening on + targetPort: 3000 + #-- the protocol for the port. it can be TCP or UDP. TCP is the default and is recommended. + protocol: TCP + - port: 3003 + targetPort: 3003 + protocol: TCP + name: metrics + ingress: + annotations: + route.openshift.io/termination: "edge" + pdb: + enabled: false # enable it in PRODUCTION for having pod disruption budget. + minAvailable: 1 # the minimum number of pods that must be available during the disruption budget. + +crunchy: # enable it for TEST and PROD, for PR based pipelines simply use single postgres + enabled: false + + crunchyImage: artifacts.developer.gov.bc.ca/bcgov-docker-local/crunchy-postgres-gis:ubi8-15.2-3.3-0 + + postgresVersion: 15 + postGISVersion: "3.3" + imagePullPolicy: Always + instances: + name: ha # high availability + replicas: 1 # 2 or 3 for high availability in TEST and PROD. + metadata: + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "9187" + dataVolumeClaimSpec: + storage: 120Mi + storageClassName: netapp-block-standard + requests: + cpu: 25m + memory: 256Mi + limits: + cpu: 100m + memory: 512Mi + replicaCertCopy: + requests: + cpu: 1m + memory: 32Mi + limits: + cpu: 50m + memory: 64Mi + + pgBackRest: + enabled: false + image: # it's not necessary to specify an image as the images specified in the Crunchy Postgres Operator will be pulled by default + retention: "1" # Ideally a larger number such as 30 backups/days + # If retention-full-type set to 'count' then the oldest backups will expire when the number of backups reach the number defined in retention + # If retention-full-type set to 'time' then the number defined in retention will take that many days worth of full backups before expiration + retentionFullType: count + repos: + schedules: + full: 0 8 * * * + incremental: 0 0,4,12,16,20 * * * + volume: + accessModes: "ReadWriteOnce" + storage: 64Mi + storageClassName: netapp-file-backup + repoHost: + requests: + cpu: 1m + memory: 64Mi + limits: + cpu: 50m + memory: 128Mi + sidecars: + requests: + cpu: 1m + memory: 64Mi + limits: + cpu: 50m + memory: 128Mi + + patroni: + postgresql: + pg_hba: "host all all 0.0.0.0/0 md5" + parameters: + shared_buffers: 16MB # default is 128MB; a good tuned default for shared_buffers is 25% of the memory allocated to the pod + wal_buffers: "64kB" # this can be set to -1 to automatically set as 1/32 of shared_buffers or 64kB, whichever is larger + min_wal_size: 32MB + max_wal_size: 64MB # default is 1GB + max_slot_wal_keep_size: 128MB # default is -1, allowing unlimited wal growth when replicas fall behind + + proxy: + pgBouncer: + image: # it's not necessary to specify an image as the images specified in the Crunchy Postgres Operator will be pulled by default + replicas: 1 + requests: + cpu: 1m + memory: 64Mi + limits: + cpu: 50m + memory: 128Mi + + # Postgres Cluster resource values: + pgmonitor: + enabled: false + exporter: + image: # it's not necessary to specify an image as the images specified in the Crunchy Postgres Operator will be pulled by default + requests: + cpu: 1m + memory: 64Mi + limits: + cpu: 50m + memory: 128Mi + +bitnami-pg: + enabled: true + image: + registry: ghcr.io + repository: bcgov/nr-containers/bitnami/postgresql + tag: 15.7.0 + auth: + existingSecret: "{{ .Release.Name }}-database" + username: "nr-compliance-enforcement" + database: nr-compliance-enforcement + shmVolume: + enabled: false + backup: + enabled: false + cronjob: + containerSecurityContext: {} + podSecurityContext: + enabled: false + storage: + size: 256Mi + primary: + persistence: + enabled: true + storageClass: netapp-block-standard + accessModes: + - ReadWriteOnce + size: 256Mi + containerSecurityContext: + enabled: false + podSecurityContext: + enabled: false + initdb: + scripts: # remove the below script, if POSTGIS is not required. + postgis.sh: | + #!/bin/sh + PGPASSWORD=$POSTGRES_PASSWORD psql -U postgres -d postgres -c "CREATE EXTENSION postgis;" + resources: + requests: + cpu: 100m + memory: 250Mi + limits: + cpu: 200m + memory: 500Mi + +backup: + enabled: true + pvc: + enabled: true + size: 256Mi + storageClassName: netapp-file-standard + accessModes: ReadWriteOnce + cronjob: + enabled: true + volumes: + - name: "{{.Release.Name}}-backup" + persistentVolumeClaim: + claimName: "{{.Release.Name}}-backup" + restartPolicy: "Never" + schedule: "0 0 * * *" + concurrencyPolicy: "Replace" + failedJobsHistoryLimit: 7 + successfulJobsHistoryLimit: 30 + startingDeadlineSeconds: 3600 + containers: + - name: backup + registry: "docker.io" + repository: "bcgovimages" # example, it includes registry and repository + image: backup-container # the exact component name, be it backend, api-1 etc... + tag: latest # the tag of the image, it can be latest, 1.0.0 etc..., or the sha256 hash + command: + - "/bin/bash" + - "-c" + - "/backup.sh -1" + volumeMounts: + - mountPath: "/backups/" + name: "{{.Release.Name}}-backup" + env: + fromValues: + - name: BACKUP_DIR + value: "/backups/" + - name: BACKUP_STRATEGY + value: "rolling" + - name: NUM_BACKUPS + value: "5" + - name: DAILY_BACKUPS + value: "7" + - name: WEEKLY_BACKUPS + value: "4" + - name: MONTHLY_BACKUPS + value: "1" + - name: DATABASE_SERVICE_NAME # depends on which chart being used, adjust accordingly. + value: "{{.Release.Name}}-{{.Values.global.databaseAlias}}" + - name: DEFAULT_PORT + value: "5432" + fromGlobalSecret: + - name: DATABASE_PASSWORD + key: password + - name: POSTGRESQL_DATABASE + key: databaseName + - name: DATABASE_USER + key: databaseUser + resources: + limits: + cpu: 50m + memory: 256Mi + requests: + cpu: 20m + memory: 128Mi + +#-- the components of the application, backend. +webeoc: + #-- enable or disable backend + enabled: true + #-- the deployment strategy, can be "Recreate" or "RollingUpdate" + deploymentStrategy: Recreate + #-- autoscaling for the component. it is optional and is an object. + autoscaling: + #-- enable or disable autoscaling. + enabled: true + #-- the minimum number of replicas. + minReplicas: 1 + #-- the maximum number of replicas. + maxReplicas: 2 + #-- the target cpu utilization percentage, is from request cpu and NOT LIMIT CPU. + targetCPUUtilizationPercentage: 80 + service: + #-- the type of the service. it can be ClusterIP, NodePort, LoadBalancer, ExternalName. ClusterIP is the default and is recommended. + type: ClusterIP + port: 80 # this is the service port, where it will be exposed internal to the namespace. + targetPort: 3002 # this is container port where app listens on + pdb: + enabled: false # enable it in PRODUCTION for having pod disruption budget. + minAvailable: 1 # the minimum number of pods that must be available during the disruption budget. diff --git a/common/graphics/cypress-artifacts.png b/common/graphics/cypress-artifacts.png deleted file mode 100644 index 1ac843a9f..000000000 Binary files a/common/graphics/cypress-artifacts.png and /dev/null differ diff --git a/common/graphics/deployments-endpoints-dev-environment.png b/common/graphics/deployments-endpoints-dev-environment.png deleted file mode 100644 index ced9441db..000000000 Binary files a/common/graphics/deployments-endpoints-dev-environment.png and /dev/null differ diff --git a/common/graphics/dev-endpoints-on-pr.png b/common/graphics/dev-endpoints-on-pr.png deleted file mode 100644 index 85024e3d7..000000000 Binary files a/common/graphics/dev-endpoints-on-pr.png and /dev/null differ diff --git a/common/graphics/main-merge.png b/common/graphics/main-merge.png deleted file mode 100644 index daf246e31..000000000 Binary files a/common/graphics/main-merge.png and /dev/null differ diff --git a/common/graphics/merge-main.png b/common/graphics/merge-main.png deleted file mode 100644 index 2b83b005b..000000000 Binary files a/common/graphics/merge-main.png and /dev/null differ diff --git a/common/graphics/packages.png b/common/graphics/packages.png deleted file mode 100644 index 765483168..000000000 Binary files a/common/graphics/packages.png and /dev/null differ diff --git a/common/graphics/pr-close.png b/common/graphics/pr-close.png deleted file mode 100644 index 9c8402181..000000000 Binary files a/common/graphics/pr-close.png and /dev/null differ diff --git a/common/graphics/pr-open.png b/common/graphics/pr-open.png deleted file mode 100644 index 7b90f42e7..000000000 Binary files a/common/graphics/pr-open.png and /dev/null differ diff --git a/common/graphics/production-review-guard.png b/common/graphics/production-review-guard.png deleted file mode 100644 index 1a14cede4..000000000 Binary files a/common/graphics/production-review-guard.png and /dev/null differ diff --git a/common/graphics/template.png b/common/graphics/template.png deleted file mode 100644 index b04b353a2..000000000 Binary files a/common/graphics/template.png and /dev/null differ diff --git a/common/graphics/unit-tests.png b/common/graphics/unit-tests.png deleted file mode 100644 index 985dd964d..000000000 Binary files a/common/graphics/unit-tests.png and /dev/null differ diff --git a/common/graphics/workflow-list.png b/common/graphics/workflow-list.png deleted file mode 100644 index 531ab8c1e..000000000 Binary files a/common/graphics/workflow-list.png and /dev/null differ diff --git a/common/openshift.init.yml b/common/openshift.init.yml deleted file mode 100644 index 68c5b8076..000000000 --- a/common/openshift.init.yml +++ /dev/null @@ -1,65 +0,0 @@ -apiVersion: template.openshift.io/v1 -kind: Template -parameters: - - name: NAME - description: Product name - value: nr-compliance-enforcement - - name: PG_DATABASE - description: Postgres database name - value: database - - name: ZONE - description: Deployment zone, e.g. pr-### or prod - required: true - - name: PROMOTE - description: Dummy param, for convenience in deployments - - name: DB_PASSWORD - description: Password for the PostgreSQL connection user. - from: "[a-zA-Z0-9]{16}" - generate: expression -objects: - - apiVersion: v1 - kind: Secret - metadata: - name: ${NAME}-${ZONE}-case-management - labels: - app: ${NAME}-${ZONE} - stringData: - case-management-api-url: "https://dc0a4a-compenf-dev-static-backend.apps.emerald.devops.gov.bc.ca/graphql" - - apiVersion: v1 - kind: Secret - metadata: - name: ${NAME}-${ZONE}-${PG_DATABASE} - labels: - app: ${NAME}-${ZONE} - stringData: - database-name: ${NAME} - database-password: ${DB_PASSWORD} - database-user: ${NAME} - - apiVersion: networking.k8s.io/v1 - kind: NetworkPolicy - metadata: - name: allow-from-openshift-ingress - labels: - template: openshift-test - spec: - podSelector: {} - ingress: - - from: - - namespaceSelector: - matchLabels: - network.openshift.io/policy-group: ingress - policyTypes: - - Ingress - - apiVersion: networking.k8s.io/v1 - kind: NetworkPolicy - metadata: - name: allow-same-namespace - labels: - template: quickstart-network-security-policy - spec: - podSelector: {} - ingress: - - from: - - podSelector: {} - policyTypes: - - Ingress diff --git a/docker-compose.yml b/docker-compose.yml index 324d9daa1..ebbe95737 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -23,15 +23,15 @@ services: volumes: - /pgdata database-migrations: - image: flyway/flyway:9.10-alpine + image: flyway/flyway:10-alpine container_name: backend-migrations command: - info - migrate - -outOfOrder=true volumes: - - "./backend/db/migrations:/flyway/sql" - - "./backend/db/test-only-migrations:/flyway/sql-test" + - "./migrations/migrations:/flyway/sql" + - "./migrations/test-only-migrations:/flyway/sql-test" environment: - FLYWAY_URL=jdbc:postgresql://database:5432/postgres - FLYWAY_USER=postgres diff --git a/frontend/Caddyfile b/frontend/Caddyfile index 2d8517559..6d2eb7d24 100644 --- a/frontend/Caddyfile +++ b/frontend/Caddyfile @@ -2,6 +2,7 @@ auto_https off admin off } + :3000 { log { output stdout @@ -12,17 +13,17 @@ level {$LOG_LEVEL} } handle /static/js/config.js { - header { - Content-Type text/javascript - } - respond `window.REACT_APP_KEYCLOAK_URL="{$KEYCLOAK_URL}"; - window.REACT_APP_KEYCLOAK_REALM="standard"; - window.REACT_APP_KEYCLOAK_CLIENT_ID="compliance-and-enforcement-digital-services-web-4794"; - window.REACT_APP_API_URL="/api"; - window.REACT_APP_COMS_URL="{$COMS_URL}"; - window.REACT_APP_COMS_BUCKET="{$COMS_BUCKET}"; - window.REACT_APP_ENVIRONMENT_NAME="{$ENVIRONMENT_NAME}"; - window.REACT_APP_SHOW_EXPERIMENTAL_FEATURES="{$SHOW_EXPERIMENTAL_FEATURES}"` + header { + Content-Type text/javascript + } + respond `window.REACT_APP_KEYCLOAK_URL="{$KEYCLOAK_URL}"; + window.REACT_APP_KEYCLOAK_REALM="standard"; + window.REACT_APP_KEYCLOAK_CLIENT_ID="compliance-and-enforcement-digital-services-web-4794"; + window.REACT_APP_API_URL="/api"; + window.REACT_APP_COMS_URL="{$COMS_URL}"; + window.REACT_APP_COMS_BUCKET="{$COMS_BUCKET}"; + window.REACT_APP_ENVIRONMENT_NAME="{$ENVIRONMENT_NAME}"; + window.REACT_APP_SHOW_EXPERIMENTAL_FEATURES="{$SHOW_EXPERIMENTAL_FEATURES}"` } root * /app/dist @@ -47,13 +48,14 @@ Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate" X-Content-Type-Options "nosniff" Strict-Transport-Security "max-age=31536000" - Content-Security-Policy "default-src 'self' https://*.gov.bc.ca data:; script-src https://*.gov.bc.ca 'self' 'unsafe-eval' https://www2.gov.bc.ca ;style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://use.fontawesome.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https://fonts.googleapis.com http://www.w3.org https://*.gov.bc.ca https://*.tile.openstreetmap.org" + Content-Security-Policy "default-src 'self' https://*.gov.bc.ca data:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.gov.bc.ca https://www2.gov.bc.ca; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://use.fontawesome.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https://fonts.googleapis.com http://www.w3.org https://*.gov.bc.ca https://*.tile.openstreetmap.org" Referrer-Policy "same-origin" Feature-Policy "fullscreen 'self'; camera 'none'; microphone 'none'" } } + :3001 { handle /health { respond "OK" } -} +} \ No newline at end of file diff --git a/frontend/openshift.deploy.yml b/frontend/openshift.deploy.yml deleted file mode 100644 index 85700ca72..000000000 --- a/frontend/openshift.deploy.yml +++ /dev/null @@ -1,208 +0,0 @@ -apiVersion: template.openshift.io/v1 -kind: Template -labels: - app: ${NAME}-${ZONE} - app.kubernetes.io/part-of: ${NAME}-${ZONE} -parameters: - - name: NAME - description: Module name - value: nr-compliance-enforcement - - name: COMPONENT - description: Component name - value: frontend - - name: ZONE - description: Deployment zone, e.g. pr-### or prod - required: true - - name: IMAGE_TAG - description: Image tag to use - value: latest - - name: DOMAIN - value: apps.silver.devops.gov.bc.ca - - name: CPU_REQUEST - value: "25m" - - name: MEMORY_REQUEST - value: "50Mi" - - name: CPU_LIMIT - value: "50m" - - name: MEMORY_LIMIT - value: "100Mi" - - name: MIN_REPLICAS - description: The minimum amount of replicas for the horizontal pod autoscaler. - value: "3" - - name: MAX_REPLICAS - description: The maximum amount of replicas for the horizontal pod autoscaler. - value: "5" - - name: REGISTRY - description: Container registry to import from (internal is image-registry.openshift-image-registry.svc:5000) - value: ghcr.io - - name: PROMOTE - description: Image (namespace/name:tag) to promote/import - value: bcgov/nr-compliance-enforcement/frontend:prod - - name: KEYCLOAK_URL - description: Keycloak auth url - value: https://dev.loginproxy.gov.bc.ca/auth - - name: COMS_URL - description: COMS URL - value: https://coms-dev.api.gov.bc.ca/api/v1 - - name: COMS_BUCKET - description: COMS BUCKET - value: "b105c416-21cd-44fa-8f5b-175d6ca56e93" - - name: LOG_LEVEL - description: Caddy logging level DEBUG, INFO, WARN, ERROR, PANIC, and FATAL (https://github.com/caddyserver/caddy/blob/master/logging.go) - value: "info" - - name: SHOW_EXPERIMENTAL_FEATURES - description: Hides or shows experimental features - value: "false" - - name: ENVIRONMENT_NAME - description: Used to show a banner in the dev and test environments - value: "production" -objects: - - apiVersion: v1 - kind: ImageStream - metadata: - labels: - app: ${NAME}-${ZONE} - name: ${NAME}-${ZONE}-${COMPONENT} - spec: - lookupPolicy: - local: false - tags: - - name: ${IMAGE_TAG} - from: - kind: DockerImage - name: ${REGISTRY}/${PROMOTE} - referencePolicy: - type: Local - - - apiVersion: v1 - kind: DeploymentConfig - metadata: - labels: - app: ${NAME}-${ZONE} - name: ${NAME}-${ZONE}-${COMPONENT} - spec: - replicas: 1 - triggers: - - type: ConfigChange - - type: ImageChange - imageChangeParams: - automatic: true - containerNames: - - ${NAME} - from: - kind: ImageStreamTag - name: ${NAME}-${ZONE}-${COMPONENT}:${IMAGE_TAG} - selector: - deploymentconfig: ${NAME}-${ZONE}-${COMPONENT} - strategy: - type: Rolling - template: - metadata: - labels: - app: ${NAME}-${ZONE} - deploymentconfig: ${NAME}-${ZONE}-${COMPONENT} - spec: - containers: - - image: ${NAME}-${ZONE}-${COMPONENT}:${IMAGE_TAG} - securityContext: - capabilities: - add: ["NET_BIND_SERVICE"] - imagePullPolicy: Always - name: ${NAME} - env: - - name: BACKEND_URL - value: http://${NAME}-${ZONE}-backend - - name: KEYCLOAK_URL - value: ${KEYCLOAK_URL} - - name: COMS_URL - value: ${COMS_URL} - - name: COMS_BUCKET - value: ${COMS_BUCKET} - - name: LOG_LEVEL - value: ${LOG_LEVEL} - - name: SHOW_EXPERIMENTAL_FEATURES - valueFrom: - secretKeyRef: - name: react-app - key: show-experimental-features - - name: ENVIRONMENT_NAME - value: ${ENVIRONMENT_NAME} - ports: - - containerPort: 3000 - protocol: TCP - resources: - requests: - cpu: ${CPU_REQUEST} - memory: ${MEMORY_REQUEST} - limits: - cpu: ${CPU_LIMIT} - memory: ${MEMORY_LIMIT} - readinessProbe: - httpGet: - path: /health - port: 3001 - scheme: HTTP - initialDelaySeconds: 5 - periodSeconds: 2 - timeoutSeconds: 1 - successThreshold: 1 - failureThreshold: 30 - livenessProbe: - successThreshold: 1 - failureThreshold: 3 - httpGet: - path: /health - port: 3001 - scheme: HTTP - initialDelaySeconds: 30 - periodSeconds: 30 - timeoutSeconds: 5 - - apiVersion: v1 - kind: Service - metadata: - labels: - app: ${NAME}-${ZONE} - name: ${NAME}-${ZONE}-${COMPONENT} - spec: - ports: - - name: 3000-tcp - protocol: TCP - port: 80 - targetPort: 3000 - selector: - deploymentconfig: ${NAME}-${ZONE}-${COMPONENT} - - apiVersion: route.openshift.io/v1 - kind: Route - metadata: - labels: - app: ${NAME}-${ZONE} - name: ${NAME}-${ZONE}-${COMPONENT} - spec: - host: ${NAME}-${ZONE}-${COMPONENT}.${DOMAIN} - port: - targetPort: 3000-tcp - to: - kind: Service - name: ${NAME}-${ZONE}-${COMPONENT} - weight: 100 - tls: - termination: edge - insecureEdgeTerminationPolicy: Redirect - - apiVersion: autoscaling/v2 - kind: HorizontalPodAutoscaler - metadata: - name: ${NAME}-${ZONE}-${COMPONENT} - spec: - scaleTargetRef: - apiVersion: apps.openshift.io/v1 - kind: DeploymentConfig - name: ${NAME}-${ZONE}-${COMPONENT} - minReplicas: ${{MIN_REPLICAS}} - maxReplicas: ${{MAX_REPLICAS}} - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 100 diff --git a/frontend/package.json b/frontend/package.json index 8a509099f..cce62e34f 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { - "name": "nr-sample-frontend", - "version": "0.5.0", + "name": "nr-sample-natcomplaints", + "version": "1.0.1", "private": true, "dependencies": { "@faker-js/faker": "^8.0.2", diff --git a/migrations/migrations/R__staging-metadata-mapping.sql b/migrations/migrations/R__staging-metadata-mapping.sql index 1171decbc..0b1942608 100644 --- a/migrations/migrations/R__staging-metadata-mapping.sql +++ b/migrations/migrations/R__staging-metadata-mapping.sql @@ -24405,4 +24405,4 @@ VALUES CURRENT_TIMESTAMP, 'FLYWAY', CURRENT_TIMESTAMP - ) on conflict do nothing; \ No newline at end of file + ) on conflict do nothing; diff --git a/migrations/test-only-migrations/R__Test-Data-Creation.sql b/migrations/test-only-migrations/R__Test-Data-Creation.sql index ea9755229..f8c8d9387 100644 --- a/migrations/test-only-migrations/R__Test-Data-Creation.sql +++ b/migrations/test-only-migrations/R__Test-Data-Creation.sql @@ -1471,4 +1471,4 @@ ON CONFLICT DO NOTHING; INSERT INTO public.gir_complaint (gir_complaint_guid, gir_type_code, create_user_id, create_utc_timestamp, update_user_id, update_utc_timestamp, complaint_identifier) VALUES('eafd661b-4c18-4aa6-a39e-a70a5462d4af'::uuid, 'QUERY', 'FLYWAY', '2024-07-11 21:18:23.336', 'FLYWAY', '2024-07-11 21:18:23.336', '23-900005') -ON CONFLICT DO NOTHING; \ No newline at end of file +ON CONFLICT DO NOTHING; diff --git a/webeoc/openshift.deploy.yml b/webeoc/openshift.deploy.yml deleted file mode 100644 index 4194fff3b..000000000 --- a/webeoc/openshift.deploy.yml +++ /dev/null @@ -1,200 +0,0 @@ -apiVersion: template.openshift.io/v1 -kind: Template -labels: - app: ${NAME}-${ZONE} - app.kubernetes.io/part-of: ${NAME}-${ZONE} -parameters: - - name: NAME - description: Module name - value: nr-compliance-enforcement - - name: COMPONENT - description: Component name - value: webeoc - - name: ZONE - description: Deployment zone, e.g. pr-### or prod - required: true - - name: IMAGE_TAG - description: Image tag to use - value: latest - - name: DOMAIN - value: apps.silver.devops.gov.bc.ca - - name: CPU_REQUEST - value: "40m" - - name: MEMORY_REQUEST - value: "75Mi" - - name: CPU_LIMIT - value: "80m" - - name: MEMORY_LIMIT - value: "150Mi" - - name: MIN_REPLICAS - description: The minimum amount of replicas for the horizontal pod autoscaler. - value: "2" - - name: MAX_REPLICAS - description: The maximum amount of replicas for the horizontal pod autoscaler. - value: "3" - - name: REGISTRY - description: Container registry to import from (internal is image-registry.openshift-image-registry.svc:5000) - value: ghcr.io - - name: PROMOTE - description: Image (namespace/name:tag) to promote/import - value: bcgov/nr-compliance-enforcement/webeoc:prod -objects: - - apiVersion: v1 - kind: ImageStream - metadata: - labels: - app: ${NAME}-${ZONE} - name: ${NAME}-${ZONE}-${COMPONENT} - spec: - lookupPolicy: - local: false - tags: - - name: ${IMAGE_TAG} - from: - kind: DockerImage - name: ${REGISTRY}/${PROMOTE} - referencePolicy: - type: Local - - apiVersion: v1 - kind: DeploymentConfig - metadata: - labels: - app: ${NAME}-${ZONE} - name: ${NAME}-${ZONE}-${COMPONENT} - spec: - replicas: 1 - triggers: - - type: ConfigChange - - type: ImageChange - imageChangeParams: - automatic: true - containerNames: - - ${NAME} - from: - kind: ImageStreamTag - name: ${NAME}-${ZONE}-${COMPONENT}:${IMAGE_TAG} - selector: - deploymentconfig: ${NAME}-${ZONE}-${COMPONENT} - strategy: - type: Rolling - template: - metadata: - labels: - app: ${NAME}-${ZONE} - deploymentconfig: ${NAME}-${ZONE}-${COMPONENT} - spec: - containers: - - image: ${NAME}-${ZONE}-${COMPONENT}:${IMAGE_TAG} - imagePullPolicy: Always - name: ${NAME} - env: - - name: NODE_TLS_REJECT_UNAUTHORIZED - value: "0" - - name: NATS_HOST - value: nats://${NAME}-${ZONE}-nats:4222 - - name: COMPLAINTS_MANAGEMENT_API_URL - value: https://${NAME}-${ZONE}-frontend.${DOMAIN}/api/v1 - - name: COMPLAINTS_API_KEY - valueFrom: - secretKeyRef: - name: webeoc - key: complaints-api-key - - name: WEBEOC_USERNAME - valueFrom: - secretKeyRef: - name: webeoc - key: webeoc-username - - name: WEBEOC_PASSWORD - valueFrom: - secretKeyRef: - name: webeoc - key: webeoc-password - - name: WEBEOC_POSITION - valueFrom: - secretKeyRef: - name: webeoc - key: webeoc-position - - name: WEBEOC_INCIDENT - valueFrom: - secretKeyRef: - name: webeoc - key: webeoc-incident - - name: WEBEOC_URL - valueFrom: - secretKeyRef: - name: webeoc - key: webeoc-url - - name: WEBEOC_COMPLAINT_HISTORY_SECONDS - valueFrom: - secretKeyRef: - name: webeoc - key: webeoc-complaint-history-seconds - - name: WEBEOC_CRON_EXPRESSION - valueFrom: - secretKeyRef: - name: webeoc - key: webeoc-cron-expression - ports: - - containerPort: 3002 - protocol: TCP - resources: - requests: - cpu: ${CPU_REQUEST} - memory: ${MEMORY_REQUEST} - limits: - cpu: ${CPU_LIMIT} - memory: ${MEMORY_LIMIT} - readinessProbe: - exec: - command: - - /usr/bin/env - - bash - - -c - - ls - initialDelaySeconds: 60 - periodSeconds: 15 - timeoutSeconds: 15 - livenessProbe: - successThreshold: 1 - failureThreshold: 3 - exec: - command: - - /usr/bin/env - - bash - - -c - - ls - initialDelaySeconds: 60 - periodSeconds: 30 - timeoutSeconds: 15 - - apiVersion: v1 - kind: Service - metadata: - labels: - app: ${NAME}-${ZONE} - name: ${NAME}-${ZONE}-${COMPONENT} - spec: - ports: - - name: 3002-tcp - protocol: TCP - port: 80 - targetPort: 3002 - selector: - deploymentconfig: ${NAME}-${ZONE}-${COMPONENT} - - apiVersion: autoscaling/v2 - kind: HorizontalPodAutoscaler - metadata: - name: ${NAME}-${ZONE}-${COMPONENT} - spec: - scaleTargetRef: - apiVersion: apps.openshift.io/v1 - kind: DeploymentConfig - name: ${NAME}-${ZONE}-${COMPONENT} - minReplicas: ${{MIN_REPLICAS}} - maxReplicas: ${{MAX_REPLICAS}} - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 100 diff --git a/webeoc/src/webeoc-complaints-scheduler/webeoc-complaints-scheduler.service.ts b/webeoc/src/webeoc-complaints-scheduler/webeoc-complaints-scheduler.service.ts index a54baf6cf..35297ca93 100644 --- a/webeoc/src/webeoc-complaints-scheduler/webeoc-complaints-scheduler.service.ts +++ b/webeoc/src/webeoc-complaints-scheduler/webeoc-complaints-scheduler.service.ts @@ -58,7 +58,9 @@ export class WebEOCComplaintsScheduler { } private async authenticateWithWebEOC(): Promise { + this.logger.debug(`Grabbing complaints from ${process.env.WEBEOC_URL}`); const authUrl = `${process.env.WEBEOC_URL}/sessions`; + const credentials = { username: process.env.WEBEOC_USERNAME, password: process.env.WEBEOC_PASSWORD,