From dd2aa2eb3aa702af1f9ba643ab4921b9b04a6484 Mon Sep 17 00:00:00 2001 From: Kuan Fan <31664961+kuanfandevops@users.noreply.github.com> Date: Fri, 29 Jul 2022 12:34:29 -0700 Subject: [PATCH] Tracking pull request to merge release-1.6.0 to main (#228) * update to 1.6.0 * add search field to GER application admin console (#230) * itvr-357--scan-uploaded-files (#229) * helm clamav (#231) * reorg chat folder and start to add app charts (#232) * Itvr 340 missing bcsc fields (#233) * initial commit * add prop from spouseForm * disable submit button * disable submit button for spouseForm * itvr-367--small-fixes (#234) * itvr-293--accessibility (#237) * Itvr 361 (#236) * initial commit * update cancellation email body * send email * implement CR suggestions * send email after status is updated * save queryset to list for iteration * tracker-update (#238) * itvr-375--cleanup-tasks (#240) * small fix (#241) * snowplow link tracking (#242) * add CORS_ORIGIN_WHITELIST * add helm for frontend and backend (#243) Co-authored-by: vibhiquartech <105294710+vibhiquartech@users.noreply.github.com> Co-authored-by: tim738745 <98717409+tim738745@users.noreply.github.com> --- .pipeline/lib/config.js | 6 +- .pipeline/lib/deploy.js | 6 +- chart/itvr-apps/Chart.yaml | 0 .../itvr-apps/charts/itvr-backend/Chart.yaml | 24 ++ .../charts/itvr-backend/templates/NOTES.txt | 22 ++ .../itvr-backend/templates/_helpers.tpl | 150 +++++++++++ .../templates/deploymentconfig.yaml | 237 ++++++++++++++++++ .../itvr-backend/templates/djangosalt.yaml | 9 + .../itvr-backend/templates/djangosecret.yaml | 10 + .../charts/itvr-backend/templates/hpa.yaml | 32 +++ .../itvr-backend/templates/imagestream.yaml | 19 ++ .../itvr-backend/templates/ingress.yaml | 61 +++++ .../charts/itvr-backend/templates/route.yaml | 20 ++ .../itvr-backend/templates/service.yaml | 16 ++ .../charts/itvr-backend/values-dev.yaml | 111 ++++++++ .../charts/itvr-backend/values-prod.yaml | 85 +++++++ .../charts/itvr-backend/values-test.yaml | 85 +++++++ .../itvr-apps/charts/itvr-backend/values.yaml | 82 ++++++ .../charts/itvr-frontend}/.helmignore | 0 .../itvr-apps/charts/itvr-frontend/Chart.yaml | 24 ++ .../charts/itvr-frontend/templates/NOTES.txt | 22 ++ .../itvr-frontend/templates/_helpers.tpl | 140 +++++++++++ .../itvr-frontend/templates/configmap.yaml | 13 + .../templates/deploymentconfig.yaml | 82 ++++++ .../charts/itvr-frontend/templates/hpa.yaml | 28 +++ .../itvr-frontend/templates/imagestream.yaml | 19 ++ .../itvr-frontend/templates/ingress.yaml | 61 +++++ .../charts/itvr-frontend/templates/route.yaml | 20 ++ .../itvr-frontend/templates/service.yaml | 16 ++ .../templates/serviceaccount.yaml | 12 + .../charts/itvr-frontend/values-dev.yaml | 109 ++++++++ .../charts/itvr-frontend/values-prod.yaml | 85 +++++++ .../charts/itvr-frontend/values-test.yaml | 85 +++++++ .../charts/itvr-frontend/values.yaml | 82 ++++++ chart/itvr-clamav/Chart.yaml | 30 +++ chart/itvr-clamav/templates/NOTES.txt | 22 ++ chart/itvr-clamav/templates/_helpers.tpl | 62 +++++ chart/itvr-clamav/templates/deployment.yaml | 76 ++++++ chart/itvr-clamav/templates/hpa.yaml | 28 +++ chart/itvr-clamav/templates/ingress.yaml | 61 +++++ .../itvr-clamav/templates/networkpolicy.yaml | 14 ++ chart/itvr-clamav/templates/pvc.yaml | 13 + chart/itvr-clamav/templates/service.yaml | 15 ++ chart/itvr-clamav/values-dev.yaml | 85 +++++++ chart/itvr-clamav/values-prod.yaml | 85 +++++++ chart/itvr-clamav/values-test.yaml | 85 +++++++ chart/itvr-clamav/values.yaml | 82 ++++++ chart/{itvr/charts => }/itvr-minio/Chart.yaml | 0 .../itvr-minio/charts/minio-10.1.7.tgz | Bin .../itvr-minio/templates/routes.yaml | 0 .../charts => }/itvr-minio/values-dev.yaml | 0 .../charts => }/itvr-minio/values-prod.yaml | 0 .../charts => }/itvr-minio/values-test.yaml | 0 .../{itvr/charts => }/itvr-minio/values.yaml | 0 chart/itvr-spilo/.helmignore | 23 ++ chart/{itvr/charts => }/itvr-spilo/Chart.yaml | 0 chart/{itvr/charts => }/itvr-spilo/Readme.md | 0 .../itvr-spilo/templates/_helpers.tpl | 0 .../charts => }/itvr-spilo/values-dev.yaml | 0 .../charts => }/itvr-spilo/values-prod.yaml | 0 .../charts => }/itvr-spilo/values-test.yaml | 0 chart/{itvr/charts => }/spilo/Chart.yaml | 0 chart/{itvr/charts => }/spilo/docs/restore.md | 0 chart/{itvr/charts => }/spilo/docs/s3.png | Bin .../charts => }/spilo/templates/_helpers.tpl | 0 .../spilo/templates/archive-pvc.yaml | 0 .../spilo/templates/networkpolicy.yaml | 0 .../spilo/templates/poddisruptionbudget.yaml | 0 .../charts => }/spilo/templates/role.yaml | 0 .../spilo/templates/rolebinding.yaml | 0 .../charts => }/spilo/templates/secret.yaml | 0 .../spilo/templates/serviceaccount.yaml | 0 .../charts => }/spilo/templates/services.yaml | 0 .../spilo/templates/statefulset.yaml | 0 chart/{itvr/charts => }/spilo/values.yaml | 0 django/api/admin.py | 1 + django/api/apps.py | 7 +- ...electricrebateapplication_doc1_and_more.py | 34 +++ .../models/go_electric_rebate_application.py | 11 +- django/api/models/household_member.py | 11 +- .../monkey_patches/itvr_django_q/README.md | 1 + .../monkey_patches/itvr_django_q/cluster.py | 149 +++++++++++ django/api/scheduled_jobs.py | 31 ++- django/api/serializers/household_member.py | 13 +- django/api/services/clam_av.py | 6 + django/api/services/rebate.py | 6 +- django/api/settings.py | 4 + django/api/signal_receivers.py | 15 +- django/api/tasks.py | 37 ++- django/api/validators.py | 22 +- django/api/viewsets/application_form.py | 4 +- django/requirements.txt | 2 + docker-compose.yml | 7 +- frontend/package.json | 2 +- frontend/public/tracker.js | 2 +- frontend/src/components/BCEIDLogin.js | 2 +- frontend/src/components/DetailsTable.js | 2 +- frontend/src/components/Footer.js | 2 +- frontend/src/components/Form.js | 12 +- frontend/src/components/Header.js | 12 +- frontend/src/components/InfoTable.js | 22 +- frontend/src/components/Layout.js | 1 + frontend/src/components/Logout.js | 6 +- frontend/src/components/SpouseForm.js | 29 ++- frontend/src/components/upload/Upload.js | 4 +- frontend/src/keycloak.js | 20 ++ frontend/src/styles/Header.scss | 4 + frontend/src/styles/index.scss | 6 + openshift/templates/backend/backend-dc.yaml | 147 ++++++----- openshift/templates/clamav/clamav-dc.yaml | 4 +- openshift/templates/knp/knp-diagram.drawio | 2 +- openshift/templates/knp/knp-env-pr.yaml | 6 +- 112 files changed, 2943 insertions(+), 157 deletions(-) create mode 100644 chart/itvr-apps/Chart.yaml create mode 100644 chart/itvr-apps/charts/itvr-backend/Chart.yaml create mode 100644 chart/itvr-apps/charts/itvr-backend/templates/NOTES.txt create mode 100644 chart/itvr-apps/charts/itvr-backend/templates/_helpers.tpl create mode 100644 chart/itvr-apps/charts/itvr-backend/templates/deploymentconfig.yaml create mode 100644 chart/itvr-apps/charts/itvr-backend/templates/djangosalt.yaml create mode 100644 chart/itvr-apps/charts/itvr-backend/templates/djangosecret.yaml create mode 100644 chart/itvr-apps/charts/itvr-backend/templates/hpa.yaml create mode 100644 chart/itvr-apps/charts/itvr-backend/templates/imagestream.yaml create mode 100644 chart/itvr-apps/charts/itvr-backend/templates/ingress.yaml create mode 100644 chart/itvr-apps/charts/itvr-backend/templates/route.yaml create mode 100644 chart/itvr-apps/charts/itvr-backend/templates/service.yaml create mode 100644 chart/itvr-apps/charts/itvr-backend/values-dev.yaml create mode 100644 chart/itvr-apps/charts/itvr-backend/values-prod.yaml create mode 100644 chart/itvr-apps/charts/itvr-backend/values-test.yaml create mode 100644 chart/itvr-apps/charts/itvr-backend/values.yaml rename chart/{itvr/charts/itvr-spilo => itvr-apps/charts/itvr-frontend}/.helmignore (100%) create mode 100644 chart/itvr-apps/charts/itvr-frontend/Chart.yaml create mode 100644 chart/itvr-apps/charts/itvr-frontend/templates/NOTES.txt create mode 100644 chart/itvr-apps/charts/itvr-frontend/templates/_helpers.tpl create mode 100644 chart/itvr-apps/charts/itvr-frontend/templates/configmap.yaml create mode 100644 chart/itvr-apps/charts/itvr-frontend/templates/deploymentconfig.yaml create mode 100644 chart/itvr-apps/charts/itvr-frontend/templates/hpa.yaml create mode 100644 chart/itvr-apps/charts/itvr-frontend/templates/imagestream.yaml create mode 100644 chart/itvr-apps/charts/itvr-frontend/templates/ingress.yaml create mode 100644 chart/itvr-apps/charts/itvr-frontend/templates/route.yaml create mode 100644 chart/itvr-apps/charts/itvr-frontend/templates/service.yaml create mode 100644 chart/itvr-apps/charts/itvr-frontend/templates/serviceaccount.yaml create mode 100644 chart/itvr-apps/charts/itvr-frontend/values-dev.yaml create mode 100644 chart/itvr-apps/charts/itvr-frontend/values-prod.yaml create mode 100644 chart/itvr-apps/charts/itvr-frontend/values-test.yaml create mode 100644 chart/itvr-apps/charts/itvr-frontend/values.yaml create mode 100644 chart/itvr-clamav/Chart.yaml create mode 100644 chart/itvr-clamav/templates/NOTES.txt create mode 100644 chart/itvr-clamav/templates/_helpers.tpl create mode 100644 chart/itvr-clamav/templates/deployment.yaml create mode 100644 chart/itvr-clamav/templates/hpa.yaml create mode 100644 chart/itvr-clamav/templates/ingress.yaml create mode 100644 chart/itvr-clamav/templates/networkpolicy.yaml create mode 100644 chart/itvr-clamav/templates/pvc.yaml create mode 100644 chart/itvr-clamav/templates/service.yaml create mode 100644 chart/itvr-clamav/values-dev.yaml create mode 100644 chart/itvr-clamav/values-prod.yaml create mode 100644 chart/itvr-clamav/values-test.yaml create mode 100644 chart/itvr-clamav/values.yaml rename chart/{itvr/charts => }/itvr-minio/Chart.yaml (100%) rename chart/{itvr/charts => }/itvr-minio/charts/minio-10.1.7.tgz (100%) rename chart/{itvr/charts => }/itvr-minio/templates/routes.yaml (100%) rename chart/{itvr/charts => }/itvr-minio/values-dev.yaml (100%) rename chart/{itvr/charts => }/itvr-minio/values-prod.yaml (100%) rename chart/{itvr/charts => }/itvr-minio/values-test.yaml (100%) rename chart/{itvr/charts => }/itvr-minio/values.yaml (100%) create mode 100644 chart/itvr-spilo/.helmignore rename chart/{itvr/charts => }/itvr-spilo/Chart.yaml (100%) rename chart/{itvr/charts => }/itvr-spilo/Readme.md (100%) rename chart/{itvr/charts => }/itvr-spilo/templates/_helpers.tpl (100%) rename chart/{itvr/charts => }/itvr-spilo/values-dev.yaml (100%) rename chart/{itvr/charts => }/itvr-spilo/values-prod.yaml (100%) rename chart/{itvr/charts => }/itvr-spilo/values-test.yaml (100%) rename chart/{itvr/charts => }/spilo/Chart.yaml (100%) rename chart/{itvr/charts => }/spilo/docs/restore.md (100%) rename chart/{itvr/charts => }/spilo/docs/s3.png (100%) rename chart/{itvr/charts => }/spilo/templates/_helpers.tpl (100%) rename chart/{itvr/charts => }/spilo/templates/archive-pvc.yaml (100%) rename chart/{itvr/charts => }/spilo/templates/networkpolicy.yaml (100%) rename chart/{itvr/charts => }/spilo/templates/poddisruptionbudget.yaml (100%) rename chart/{itvr/charts => }/spilo/templates/role.yaml (100%) rename chart/{itvr/charts => }/spilo/templates/rolebinding.yaml (100%) rename chart/{itvr/charts => }/spilo/templates/secret.yaml (100%) rename chart/{itvr/charts => }/spilo/templates/serviceaccount.yaml (100%) rename chart/{itvr/charts => }/spilo/templates/services.yaml (100%) rename chart/{itvr/charts => }/spilo/templates/statefulset.yaml (100%) rename chart/{itvr/charts => }/spilo/values.yaml (100%) create mode 100644 django/api/migrations/0008_alter_goelectricrebateapplication_doc1_and_more.py create mode 100644 django/api/monkey_patches/itvr_django_q/README.md create mode 100644 django/api/monkey_patches/itvr_django_q/cluster.py create mode 100644 django/api/services/clam_av.py diff --git a/.pipeline/lib/config.js b/.pipeline/lib/config.js index a83137d1..87162c22 100644 --- a/.pipeline/lib/config.js +++ b/.pipeline/lib/config.js @@ -42,7 +42,7 @@ const phases = { frontendCpuRequest: '30m', frontendCpuLimit: '60m', frontendMemoryRequest: '30Mi', frontendMemoryLimit: '60Mi', frontendReplicas: 1, reactAppBCSCKeycloakClientId: 'itvr', reactAppBCSCKeycloakRealm: 'rzh2zkjq', reactAppBCSCKeycloakUrl: 'https://dev.oidc.gov.bc.ca/auth/', reactAppApiBase: `https://itvr-backend-dev-${changeId}.apps.silver.devops.gov.bc.ca`, reactAppBCeIDKeycloakClientId: 'itvr-2674', reactAppBCeIDKeycloakRealm: 'onestopauth-basic', reactAppBCeIDKeycloakUrl: 'https://dev.oidc.gov.bc.ca/auth/', - backendCpuRequest: '60m', backendCpuLimit: '120m', backendMemoryRequest: '150Mi', backendMemoryLimit: '300Mi', backendHealthCheckDelay: 30, backendHost: `itvr-backend-dev-${changeId}.${ocpName}.gov.bc.ca`, backendReplicas: 1, backendDjangoDebug: 'True', bucketName: 'itvrdv', craEnvironment: 'A', + backendCpuRequest: '60m', backendCpuLimit: '120m', backendMemoryRequest: '150Mi', backendMemoryLimit: '300Mi', backendHealthCheckDelay: 30, backendHost: `itvr-backend-dev-${changeId}.${ocpName}.gov.bc.ca`, backendReplicas: 1, backendDjangoDebug: 'True', bucketName: 'itvrdv', craEnvironment: 'A', corsOriginWhitelist: 'https://itvr-dev.apps.silver.devops.gov.bc.ca', minioCpuRequest: '30m', minioCpuLimit: '100m', minioMemoryRequest: '150Mi', minioMemoryLimit: '300Mi', minioPvcSize: '3Gi', schemaspyCpuRequest: '50m', schemaspyCpuLimit: '200m', schemaspyMemoryRequest: '150M', schemaspyMemoryLimit: '300M', schemaspyHealthCheckDelay: 160, rabbitmqCpuRequest: '250m', rabbitmqCpuLimit: '700m', rabbitmqMemoryRequest: '500M', rabbitmqMemoryLimit: '1G', rabbitmqPvcSize: '1G', rabbitmqReplica: 1, rabbitmqPostStartSleep: 120, storageClass: 'netapp-block-standard', @@ -57,7 +57,7 @@ const phases = { frontendCpuRequest: '30m', frontendCpuLimit: '60m', frontendMemoryRequest: '30Mi', frontendMemoryLimit: '60Mi', frontendReplicas: 2, frontendMinReplicas: 1, frontendMaxReplicas: 3, reactAppBCSCKeycloakClientId: 'itvr', reactAppBCSCKeycloakRealm: 'rzh2zkjq', reactAppBCSCKeycloakUrl: 'https://test.oidc.gov.bc.ca/auth/', reactAppApiBase: `https://itvr-backend-test.apps.silver.devops.gov.bc.ca`, reactAppBCeIDKeycloakClientId: 'itvr-2674', reactAppBCeIDKeycloakRealm: 'onestopauth-basic', reactAppBCeIDKeycloakUrl: 'https://test.oidc.gov.bc.ca/auth/', - backendCpuRequest: '60m', backendCpuLimit: '120m', backendMemoryRequest: '150Mi', backendMemoryLimit: '300Mi', backendHealthCheckDelay: 30, backendReplicas: 2, backendMinReplicas: 1, backendMaxReplicas: 3, backendHost: `itvr-backend-test.${ocpName}.gov.bc.ca`, backendDjangoDebug: 'False', bucketName: 'itvrts', craEnvironment: 'A', + backendCpuRequest: '60m', backendCpuLimit: '120m', backendMemoryRequest: '150Mi', backendMemoryLimit: '300Mi', backendHealthCheckDelay: 30, backendReplicas: 2, backendMinReplicas: 1, backendMaxReplicas: 3, backendHost: `itvr-backend-test.${ocpName}.gov.bc.ca`, backendDjangoDebug: 'False', bucketName: 'itvrts', craEnvironment: 'A', corsOriginWhitelist: 'https://itvr-test.apps.silver.devops.gov.bc.ca', minioCpuRequest: '30m', minioCpuLimit: '100m', minioMemoryRequest: '150Mi', minioMemoryLimit: '300Mi', minioPvcSize: '3G', schemaspyCpuRequest: '20m', schemaspyCpuLimit: '200m', schemaspyMemoryRequest: '150M', schemaspyMemoryLimit: '300M', schemaspyHealthCheckDelay: 160, rabbitmqCpuRequest: '250m', rabbitmqCpuLimit: '700m', rabbitmqMemoryRequest: '500M', rabbitmqMemoryLimit: '700M', rabbitmqPvcSize: '1G', rabbitmqReplica: 2, rabbitmqPostStartSleep: 120, storageClass: 'netapp-block-standard', @@ -72,7 +72,7 @@ const phases = { frontendCpuRequest: '30m', frontendCpuLimit: '60m', frontendMemoryRequest: '30Mi', frontendMemoryLimit: '60Mi', frontendReplicas: 2, frontendMinReplicas: 2, frontendMaxReplicas: 5, reactAppBCSCKeycloakClientId: 'itvr', reactAppBCSCKeycloakRealm: 'rzh2zkjq', reactAppBCSCKeycloakUrl: 'https://oidc.gov.bc.ca/auth/', reactAppApiBase: `https://itvr-backend-prod.apps.silver.devops.gov.bc.ca`, reactAppBCeIDKeycloakClientId: 'itvr-2674', reactAppBCeIDKeycloakRealm: 'onestopauth-basic', reactAppBCeIDKeycloakUrl: 'https://oidc.gov.bc.ca/auth/', - backendCpuRequest: '60m', backendCpuLimit: '120m', backendMemoryRequest: '150Mi', backendMemoryLimit: '300Mi', backendHealthCheckDelay: 30, backendReplicas: 3, backendMinReplicas: 3, backendMaxReplicas: 5, backendHost: `itvr-backend-prod.${ocpName}.gov.bc.ca`, backendDjangoDebug: 'False', bucketName: 'itvrpr', craEnvironment: 'P', + backendCpuRequest: '60m', backendCpuLimit: '120m', backendMemoryRequest: '150Mi', backendMemoryLimit: '300Mi', backendHealthCheckDelay: 30, backendReplicas: 3, backendMinReplicas: 3, backendMaxReplicas: 5, backendHost: `itvr-backend-prod.${ocpName}.gov.bc.ca`, backendDjangoDebug: 'False', bucketName: 'itvrpr', craEnvironment: 'P', corsOriginWhitelist: 'https://electric-vehicle-rebates.gov.bc.ca', minioCpuRequest: '30m', minioCpuLimit: '100m', minioMemoryRequest: '150Mi', minioMemoryLimit: '300Mi', minioPvcSize: '3G', schemaspyCpuRequest: '50m', schemaspyCpuLimit: '400m', schemaspyMemoryRequest: '150M', schemaspyMemoryLimit: '300M', schemaspyHealthCheckDelay: 160, rabbitmqCpuRequest: '250m', rabbitmqCpuLimit: '700m', rabbitmqMemoryRequest: '500M', rabbitmqMemoryLimit: '1G', rabbitmqPvcSize: '5G', rabbitmqReplica: 2, rabbitmqPostStartSleep: 120, storageClass: 'netapp-block-standard', diff --git a/.pipeline/lib/deploy.js b/.pipeline/lib/deploy.js index 2986a755..20dbe870 100755 --- a/.pipeline/lib/deploy.js +++ b/.pipeline/lib/deploy.js @@ -92,7 +92,8 @@ module.exports = settings => { 'REPLICAS': phases[phase].backendReplicas, 'DJANGO_DEBUG': phases[phase].backendDjangoDebug, 'CRA_ENVIRONMENT': phases[phase].craEnvironment, - 'BUCKET_NAME': phases[phase].bucketName + 'BUCKET_NAME': phases[phase].bucketName, + 'CORS_ORIGIN_WHITELIST': phases[phase].corsOriginWhitelist } })) @@ -107,7 +108,8 @@ module.exports = settings => { 'MEMORY_LIMIT': phases[phase].taskQueueMemoryLimit, 'REPLICAS': phases[phase].taskQueueReplicas, 'CRA_ENVIRONMENT': phases[phase].craEnvironment, - 'DJANGO_DEBUG': phases[phase].taskQueueDjangoDebug + 'DJANGO_DEBUG': phases[phase].taskQueueDjangoDebug, + 'CORS_ORIGIN_WHITELIST': phases[phase].corsOriginWhitelist } })) diff --git a/chart/itvr-apps/Chart.yaml b/chart/itvr-apps/Chart.yaml new file mode 100644 index 00000000..e69de29b diff --git a/chart/itvr-apps/charts/itvr-backend/Chart.yaml b/chart/itvr-apps/charts/itvr-backend/Chart.yaml new file mode 100644 index 00000000..02ef8580 --- /dev/null +++ b/chart/itvr-apps/charts/itvr-backend/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: itvr-backend +description: A Helm chart for Kubernetes + +# 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: 1.0.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.6.0" diff --git a/chart/itvr-apps/charts/itvr-backend/templates/NOTES.txt b/chart/itvr-apps/charts/itvr-backend/templates/NOTES.txt new file mode 100644 index 00000000..d88e21bb --- /dev/null +++ b/chart/itvr-apps/charts/itvr-backend/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "itvr-backend.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "itvr-backend.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "itvr-backend.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "itvr-backend.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/chart/itvr-apps/charts/itvr-backend/templates/_helpers.tpl b/chart/itvr-apps/charts/itvr-backend/templates/_helpers.tpl new file mode 100644 index 00000000..3134ac07 --- /dev/null +++ b/chart/itvr-apps/charts/itvr-backend/templates/_helpers.tpl @@ -0,0 +1,150 @@ +{{/* + +version: 1.0.0 +appVersion: "1.6.0" +nameOverride: "" +fullnameOverride: "" + +1. deploy PR based +pr225 is the .Release.Name +Set below to to be empty string in values file + nameOverride: "" + fullnameOverride: "" +imageTools value should be the build PR image in tools project +Run the below command +helm template -f ./values-dev.yaml pr225 . + name: pr225-itvr-backend + labels: + helm.sh/chart: itvr-backend-1.0.0 + app.kubernetes.io/name: itvr-backend + app.kubernetes.io/instance: pr225 + app.kubernetes.io/version: "1.6.0" + app.kubernetes.io/managed-by: Helm + +2. only build racking PR +helm template -f ./values-dev.yaml itvr-backend . + name: itvr-backend + labels: + helm.sh/chart: itvr-backend-1.0.0 + app.kubernetes.io/name: itvr-backend + app.kubernetes.io/instance: itvr-backend + app.kubernetes.io/version: "1.6.0" + app.kubernetes.io/managed-by: Helm + +it makes PR based pipeline possible for dev environment + +At this moment, when deploy on Dev, Test and Prod, set the value for nameOverride and fullnameOverride to be itvr-backend + +*/}} + + +{{/* +Expand the name of the chart. +*/}} +{{- define "itvr-backend.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. +The .Release.Name is the first parameter of command helm install itvr-backend +*/}} +{{- define "itvr-backend.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "itvr-backend.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels: +app.kubernetes.io/managed-by would be Helm +*/}} +{{- define "itvr-backend.labels" -}} +helm.sh/chart: {{ include "itvr-backend.chart" . }} +{{ include "itvr-backend.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "itvr-backend.selectorLabels" -}} +app.kubernetes.io/name: {{ include "itvr-backend.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Define the deploymentconfig name +*/}} +{{- define "itvr-backend.deploymentconfigName" -}} +{{- include "itvr-backend.fullname" . }} +{{- end }} + +{{/* +Define the deploymentconfig name +*/}} +{{- define "itvr-backend.imagestreamName" -}} +{{- include "itvr-backend.fullname" . }} +{{- end }} + +{{/* +Define the service name +*/}} +{{- define "itvr-backend.serviceName" -}} +{{- include "itvr-backend.fullname" . }} +{{- end }} + + +{{/* +Define the route name +*/}} +{{- define "itvr-backend.routeName" -}} +{{- include "itvr-backend.fullname" . }} +{{- end }} + +{{/* +Define the djangoSecretKey +*/}} +{{- define "itvr-backend.djangoSecretKey" -}} +{{- randAlphaNum 50 | nospace | b64enc }} +{{- end }} + +{{/* +Define the djangoSaltKey +*/}} +{{- define "itvr-backend.djangoSaltKey" -}} +{{- randAlphaNum 50 | nospace | b64enc }} +{{- end }} + +{{/* +Define the django-secret name +*/}} +{{- define "itvr-backend.django-secret" -}} +itvr-django-secret-{{ .Values.envName }} +{{- end }} + +{{/* +Define the django-salt name +*/}} +{{- define "itvr-backend.django-salt" -}} +itvr-django-salt-{{ .Values.envName }} +{{- end }} \ No newline at end of file diff --git a/chart/itvr-apps/charts/itvr-backend/templates/deploymentconfig.yaml b/chart/itvr-apps/charts/itvr-backend/templates/deploymentconfig.yaml new file mode 100644 index 00000000..da3e5be3 --- /dev/null +++ b/chart/itvr-apps/charts/itvr-backend/templates/deploymentconfig.yaml @@ -0,0 +1,237 @@ +kind: DeploymentConfig +apiVersion: apps.openshift.io/v1 +metadata: + annotations: + description: Defines how to deploy the backend application + name: {{ include "itvr-backend.deploymentconfigName" . }} + labels: + {{- include "itvr-backend.labels" . | nindent 4 }} +spec: + strategy: + type: Recreate + recreateParams: + timeoutSeconds: 600 + mid: + failurePolicy: Retry + execNewPod: + command: + - /bin/sh + - '-c' + - |- + python ./manage.py migrate + python ./manage.py createcachetable + containerName: backend + resources: {} + activeDeadlineSeconds: 800 + triggers: + - type: ImageChange + imageChangeParams: + automatic: true + containerNames: + - backend + from: + kind: ImageStreamTag + namespace: {{ .Values.image.namespace }} + name: {{ include "itvr-backend.fullname" . }}:{{ .Values.imageEnv.tag }} + - type: ConfigChange + replicas: 1 + revisionHistoryLimit: 10 + test: false + selector: + {{- include "itvr-backend.selectorLabels" . | nindent 4 }} + template: + metadata: + creationTimestamp: null + labels: + {{- include "itvr-backend.labels" . | nindent 8 }} + spec: + containers: + - resources: + limits: + cpu: 120m + memory: 300Mi + requests: + cpu: 60m + memory: 150Mi + readinessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 30 + timeoutSeconds: 3 + periodSeconds: 15 + successThreshold: 1 + failureThreshold: 20 + terminationMessagePath: /dev/termination-log + name: backend + livenessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 30 + timeoutSeconds: 3 + periodSeconds: 15 + successThreshold: 1 + failureThreshold: 20 + env: + - name: ALLOWED_HOSTS + value: {{ .Values.backend.allowedHost }} + - name: CORS_ORIGIN_WHITELIST + value: {{ .Values.backend.corsOriginWhitlist }} + - name: BACKEND_ORIGIN + value: {{ .Values.backend.backendOrigin }} + - name: DB_ENGINE + value: django.db.backends.postgresql + - name: DB_HOST + value: itvr-spilo + - name: DB_HOST_READONLY + value: itvr-spilo-readonly + - name: DB_NAME + value: itvr + - name: DB_PASSWORD + valueFrom: + secretKeyRef: + name: itvr-patroni-app + key: app-db-password + - name: DB_PORT + value: '5432' + - name: DB_USER + valueFrom: + secretKeyRef: + name: itvr-patroni-app + key: app-db-username + - name: APP_CONFIG + value: /opt/app-root/src/gunicorn.cfg.py + - name: BCSC_KEYCLOAK_CLIENT_ID + valueFrom: + secretKeyRef: + name: itvr-keycloak + key: BCSC_KEYCLOAK_CLIENT_ID + - name: BCSC_KEYCLOAK_REALM + valueFrom: + secretKeyRef: + name: itvr-keycloak + key: BCSC_KEYCLOAK_REALM + - name: BCSC_KEYCLOAK_URL + valueFrom: + secretKeyRef: + name: itvr-keycloak + key: BCSC_KEYCLOAK_URL + - name: BCEID_KEYCLOAK_CLIENT_ID + valueFrom: + secretKeyRef: + name: itvr-keycloak + key: BCEID_KEYCLOAK_CLIENT_ID + - name: BCEID_KEYCLOAK_REALM + valueFrom: + secretKeyRef: + name: itvr-keycloak + key: BCEID_KEYCLOAK_REALM + - name: BCEID_KEYCLOAK_URL + valueFrom: + secretKeyRef: + name: itvr-keycloak + key: BCEID_KEYCLOAK_URL + - name: DJANGO_SECRET_KEY + valueFrom: + secretKeyRef: + name: {{ include "itvr-backend.django-secret" . }} + key: DJANGO_SECRET_KEY + - name: DJANGO_SALT_KEY + valueFrom: + secretKeyRef: + name: {{ include "itvr-backend.django-salt" . }} + key: DJANGO_SALT_KEY + - name: EMAIL_SERVICE_CLIENT_ID + valueFrom: + secretKeyRef: + name: itvr-email-service + key: EMAIL_SERVICE_CLIENT_ID + - name: EMAIL_SERVICE_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: itvr-email-service + key: EMAIL_SERVICE_CLIENT_SECRET + - name: CHES_AUTH_URL + valueFrom: + secretKeyRef: + name: itvr-email-service + key: CHES_AUTH_URL + - name: CHES_EMAIL_URL + valueFrom: + secretKeyRef: + name: itvr-email-service + key: CHES_EMAIL_URL + - name: SENDER_EMAIL + valueFrom: + secretKeyRef: + name: itvr-email-service + key: SENDER_EMAIL + - name: SENDER_NAME + valueFrom: + secretKeyRef: + name: itvr-email-service + key: SENDER_NAME + - name: SEND_EMAIL + value: '{{ .Values.backend.sendEmail }}' + - name: MINIO_ENDPOINT + valueFrom: + secretKeyRef: + name: itvr-object-storage + key: server-url + - name: MINIO_ROOT_USER + valueFrom: + secretKeyRef: + name: itvr-object-storage + key: root-user + - name: MINIO_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: itvr-object-storage + key: root-password + - name: MINIO_BUCKET_NAME + value: {{ .Values.backend.minioBucketName }} + - name: NCDA_CLIENT_ID + valueFrom: + secretKeyRef: + name: itvr-ncda + key: NCDA_CLIENT_ID + - name: NCDA_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: itvr-ncda + key: NCDA_CLIENT_SECRET + - name: NCDA_RESOURCE + valueFrom: + secretKeyRef: + name: itvr-ncda + key: NCDA_RESOURCE + - name: NCDA_AUTH_URL + valueFrom: + secretKeyRef: + name: itvr-ncda + key: NCDA_AUTH_URL + - name: NCDA_SHAREPOINT_URL + valueFrom: + secretKeyRef: + name: itvr-ncda + key: NCDA_SHAREPOINT_URL + - name: CRA_ENVIRONMENT + value: {{ .Values.backend.craEnvrionment }} + - name: DJANGO_DEBUG + value: '{{ .Values.backend.djangoDebug }}' + - name: VIRUS_SCANNING_ENABLED + value: '{{ .Values.backend.virusScanEnabled }}' + - name: CLAMD_HOST + value: itvr-clamav + - name: CLAMD_PORT + value: '3310' + ports: + - containerPort: 8080 + protocol: TCP + imagePullPolicy: IfNotPresent + terminationMessagePolicy: File + restartPolicy: Always + terminationGracePeriodSeconds: 30 + dnsPolicy: ClusterFirst + securityContext: {} + schedulerName: default-scheduler + diff --git a/chart/itvr-apps/charts/itvr-backend/templates/djangosalt.yaml b/chart/itvr-apps/charts/itvr-backend/templates/djangosalt.yaml new file mode 100644 index 00000000..c2d8e969 --- /dev/null +++ b/chart/itvr-apps/charts/itvr-backend/templates/djangosalt.yaml @@ -0,0 +1,9 @@ +kind: Secret +apiVersion: v1 +metadata: + name: {{ include "itvr-backend.django-salt" . }} + labels: + {{- include "itvr-backend.labels" . | nindent 4 }} +data: + DJANGO_SALT_KEY: {{ include "itvr-backend.djangoSaltKey" . }} +type: Opaque diff --git a/chart/itvr-apps/charts/itvr-backend/templates/djangosecret.yaml b/chart/itvr-apps/charts/itvr-backend/templates/djangosecret.yaml new file mode 100644 index 00000000..506d12ff --- /dev/null +++ b/chart/itvr-apps/charts/itvr-backend/templates/djangosecret.yaml @@ -0,0 +1,10 @@ +kind: Secret +apiVersion: v1 +metadata: + name: {{ include "itvr-backend.django-secret" . }} + creationTimestamp: null + labels: + {{- include "itvr-backend.labels" . | nindent 4 }} +data: + DJANGO_SECRET_KEY: {{ include "itvr-backend.djangoSecretKey" . }} +type: Opaque diff --git a/chart/itvr-apps/charts/itvr-backend/templates/hpa.yaml b/chart/itvr-apps/charts/itvr-backend/templates/hpa.yaml new file mode 100644 index 00000000..ce9fa5f2 --- /dev/null +++ b/chart/itvr-apps/charts/itvr-backend/templates/hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2beta2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "itvr-backend.fullname" . }} + labels: + {{- include "itvr-backend.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "itvr-backend.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/chart/itvr-apps/charts/itvr-backend/templates/imagestream.yaml b/chart/itvr-apps/charts/itvr-backend/templates/imagestream.yaml new file mode 100644 index 00000000..bcdb84b3 --- /dev/null +++ b/chart/itvr-apps/charts/itvr-backend/templates/imagestream.yaml @@ -0,0 +1,19 @@ +apiVersion: image.openshift.io/v1 +kind: ImageStream +metadata: + labels: + {{- include "itvr-backend.labels" . | nindent 4 }} + creationTimestamp: null + name: {{ include "itvr-backend.imagestreamName" . }} +spec: + lookupPolicy: + local: false + tags: + - name: {{ .Values.imageEnv.tag }} + from: + kind: ImageStreamImage + namespace: {{ .Values.toolsNamespace }} + name: {{ .Values.imageTools.tag }} + importPolicy: {} + referencePolicy: + type: Local diff --git a/chart/itvr-apps/charts/itvr-backend/templates/ingress.yaml b/chart/itvr-apps/charts/itvr-backend/templates/ingress.yaml new file mode 100644 index 00000000..facbe97b --- /dev/null +++ b/chart/itvr-apps/charts/itvr-backend/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "itvr-backend.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "itvr-backend.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/chart/itvr-apps/charts/itvr-backend/templates/route.yaml b/chart/itvr-apps/charts/itvr-backend/templates/route.yaml new file mode 100644 index 00000000..6273ed97 --- /dev/null +++ b/chart/itvr-apps/charts/itvr-backend/templates/route.yaml @@ -0,0 +1,20 @@ +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + name: {{ include "itvr-backend.routeName" . }} + annotations: + haproxy.router.openshift.io/timeout: 1500s + labels: + {{- include "itvr-backend.labels" . | nindent 4 }} +spec: + host: {{ include "itvr-backend.fullname" . }}-{{ .Values.envName }}.apps.silver.devops.gov.bc.ca + port: + targetPort: http + tls: + insecureEdgeTerminationPolicy: Redirect + termination: edge + to: + kind: Service + name: {{ include "itvr-backend.fullname" . }} + weight: 100 + wildcardPolicy: None \ No newline at end of file diff --git a/chart/itvr-apps/charts/itvr-backend/templates/service.yaml b/chart/itvr-apps/charts/itvr-backend/templates/service.yaml new file mode 100644 index 00000000..d83596bb --- /dev/null +++ b/chart/itvr-apps/charts/itvr-backend/templates/service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "itvr-backend.serviceName" . }} + labels: + {{- include "itvr-backend.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "itvr-backend.selectorLabels" . | nindent 4 }} + sessionAffinity: None diff --git a/chart/itvr-apps/charts/itvr-backend/values-dev.yaml b/chart/itvr-apps/charts/itvr-backend/values-dev.yaml new file mode 100644 index 00000000..6425af2b --- /dev/null +++ b/chart/itvr-apps/charts/itvr-backend/values-dev.yaml @@ -0,0 +1,111 @@ +# Default values for itvr-backend. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +toolsNamespace: ac294c-tools +envNamespace: ac294c-dev +envName: dev + +# decide which image in tools project will be used +imageTools: + repository: image-registry.openshift-image-registry.svc:5000 + tag: itvr-backend@sha256:02f9ffc40dc5ed1f17eb364676a9cf4c0ea111c060d0144a9df7d0c5e6211604 + pullPolicy: IfNotPresent + +# decide the imagestream will be created in env projects +# for pr based, coulde user the value fpr 1.0.0- +imageEnv: + tag: 1.0.0 + +imagePullSecrets: [] + +## For ITVR Baclend App, set the following two, will result in +## itvr-backend.fullname and itvr-backend.name are itve-backend +nameOverride: "itvr-backend" +fullnameOverride: "itvr-backend" + +#nameOverride: "" +#fullnameOverride: "" + + +serviceAccount: + # Specifies whether a service account should be created + create: false + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 8080 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 60m + memory: 60Mi + requests: + cpu: 30m + memory: 30Mi + +autoscaling: + enabled: true + minReplicas: 1 + maxReplicas: 2 + targetCPUUtilizationPercentage: 90 + targetMemoryUtilizationPercentage: 90 + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +backend: + allowedHost: itvr-backend-test.apps.silver.devops.gov.bc.ca + corsOriginWhitlist: https://itvr-test.apps.silver.devops.gov.bc.ca + backendOrigin: https://itvr-backend-test.apps.silver.devops.gov.bc.ca + djangoSecretName: itvr-django-secret-dev + djangoSaltSecretName: itvr-django-salt-dev + sendEmail: 'True' + minioBucketName: itvrdv + craEnvrionment: A + djangoDebug: 'False' + virusScanEnabled: 'True' + diff --git a/chart/itvr-apps/charts/itvr-backend/values-prod.yaml b/chart/itvr-apps/charts/itvr-backend/values-prod.yaml new file mode 100644 index 00000000..5e6a42a3 --- /dev/null +++ b/chart/itvr-apps/charts/itvr-backend/values-prod.yaml @@ -0,0 +1,85 @@ +# Default values for itvr-backend. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: image-registry.openshift-image-registry.svc:5000/ac294c-tools/itvr-backend + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "build-1.0.0-205" + +imagePullSecrets: [] + +## For ITVR Frontend App, set the following two, will result in +## itvr-backend.fullname and itvr-backend.name are itve-frontend +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: false + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 8080 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/chart/itvr-apps/charts/itvr-backend/values-test.yaml b/chart/itvr-apps/charts/itvr-backend/values-test.yaml new file mode 100644 index 00000000..5e6a42a3 --- /dev/null +++ b/chart/itvr-apps/charts/itvr-backend/values-test.yaml @@ -0,0 +1,85 @@ +# Default values for itvr-backend. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: image-registry.openshift-image-registry.svc:5000/ac294c-tools/itvr-backend + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "build-1.0.0-205" + +imagePullSecrets: [] + +## For ITVR Frontend App, set the following two, will result in +## itvr-backend.fullname and itvr-backend.name are itve-frontend +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: false + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 8080 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/chart/itvr-apps/charts/itvr-backend/values.yaml b/chart/itvr-apps/charts/itvr-backend/values.yaml new file mode 100644 index 00000000..2ef80771 --- /dev/null +++ b/chart/itvr-apps/charts/itvr-backend/values.yaml @@ -0,0 +1,82 @@ +# Default values for itvr-backend. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: nginx + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/chart/itvr/charts/itvr-spilo/.helmignore b/chart/itvr-apps/charts/itvr-frontend/.helmignore similarity index 100% rename from chart/itvr/charts/itvr-spilo/.helmignore rename to chart/itvr-apps/charts/itvr-frontend/.helmignore diff --git a/chart/itvr-apps/charts/itvr-frontend/Chart.yaml b/chart/itvr-apps/charts/itvr-frontend/Chart.yaml new file mode 100644 index 00000000..0bc528ea --- /dev/null +++ b/chart/itvr-apps/charts/itvr-frontend/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: itvr-frontend +description: A Helm chart for Kubernetes + +# 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: 1.0.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.6.0" diff --git a/chart/itvr-apps/charts/itvr-frontend/templates/NOTES.txt b/chart/itvr-apps/charts/itvr-frontend/templates/NOTES.txt new file mode 100644 index 00000000..06978c90 --- /dev/null +++ b/chart/itvr-apps/charts/itvr-frontend/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "itvr-frontend.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "itvr-frontend.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "itvr-frontend.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "itvr-frontend.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/chart/itvr-apps/charts/itvr-frontend/templates/_helpers.tpl b/chart/itvr-apps/charts/itvr-frontend/templates/_helpers.tpl new file mode 100644 index 00000000..c41352d0 --- /dev/null +++ b/chart/itvr-apps/charts/itvr-frontend/templates/_helpers.tpl @@ -0,0 +1,140 @@ +{{/* + +version: 1.0.0 +appVersion: "1.6.0" +nameOverride: "" +fullnameOverride: "" + +1. deploy PR based +pr225 is the .Release.Name +Set below to to be empty string in values file + nameOverride: "" + fullnameOverride: "" +imageTools value should be the build PR image in tools project +Run the below command +helm template -f ./values-dev.yaml pr225 . + name: pr225-itvr-frontend + labels: + helm.sh/chart: itvr-frontend-1.0.0 + app.kubernetes.io/name: itvr-frontend + app.kubernetes.io/instance: pr225 + app.kubernetes.io/version: "1.6.0" + app.kubernetes.io/managed-by: Helm + +2. only build racking PR +helm template -f ./values-dev.yaml itvr-frontend . + name: itvr-frontend + labels: + helm.sh/chart: itvr-frontend-1.0.0 + app.kubernetes.io/name: itvr-frontend + app.kubernetes.io/instance: itvr-frontend + app.kubernetes.io/version: "1.6.0" + app.kubernetes.io/managed-by: Helm + +it makes PR based pipeline possible for dev environment + +At this moment, when deploy on Dev, Test and Prod, set the value for nameOverride and fullnameOverride to be itvr-frontend + +*/}} + + +{{/* +Expand the name of the chart. +*/}} +{{- define "itvr-frontend.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. +The .Release.Name is the first parameter of command helm install itvr-frontend +*/}} +{{- define "itvr-frontend.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "itvr-frontend.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels: +app.kubernetes.io/managed-by would be Helm +*/}} +{{- define "itvr-frontend.labels" -}} +helm.sh/chart: {{ include "itvr-frontend.chart" . }} +{{ include "itvr-frontend.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "itvr-frontend.selectorLabels" -}} +app.kubernetes.io/name: {{ include "itvr-frontend.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "itvr-frontend.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "itvr-frontend.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Define the configmap name +*/}} +{{- define "itvr-frontend.configmapName" -}} +{{- include "itvr-frontend.fullname" . }}-features +{{- end }} + +{{/* +Define the deploymentconfig name +*/}} +{{- define "itvr-frontend.deploymentconfigName" -}} +{{- include "itvr-frontend.fullname" . }} +{{- end }} + +{{/* +Define the deploymentconfig name +*/}} +{{- define "itvr-frontend.imagestreamName" -}} +{{- include "itvr-frontend.fullname" . }} +{{- end }} + +{{/* +Define the service name +*/}} +{{- define "itvr-frontend.serviceName" -}} +{{- include "itvr-frontend.fullname" . }} +{{- end }} + + +{{/* +Define the route name +*/}} +{{- define "itvr-frontend.routeName" -}} +{{- include "itvr-frontend.fullname" . }} +{{- end }} \ No newline at end of file diff --git a/chart/itvr-apps/charts/itvr-frontend/templates/configmap.yaml b/chart/itvr-apps/charts/itvr-frontend/templates/configmap.yaml new file mode 100644 index 00000000..25130c12 --- /dev/null +++ b/chart/itvr-apps/charts/itvr-frontend/templates/configmap.yaml @@ -0,0 +1,13 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + name: {{ include "itvr-frontend.configmapName" . }} + creationTimestamp: +data: + features.js: "window.itvr_config = {\n \"REACT_APP_BCSC_KEYCLOAK_CLIENT_ID\": \"{{ .Values.frontend.reactAppBCSCKeycloakClientId }}\",\n + \ \"REACT_APP_BCSC_KEYCLOAK_REALM\": \" {{ .Values.frontend.reactAppBCSCKeycloakRealm }}\",\n \"REACT_APP_BCSC_KEYCLOAK_URL\": + \"{{ .Values.frontend.reactAppBCSCKeycloakUrl }}\", \n \"REACT_APP_BCEID_KEYCLOAK_CLIENT_ID\": + \"{{ .Values.frontend.reactAppBCeIDKeycloakClientId }}\",\n \"REACT_APP_BCEID_KEYCLOAK_REALM\": \"{{ .Values.frontend.reactAppBCeIDKeycloakRealm }}\",\n + \ \"REACT_APP_BCEID_KEYCLOAK_URL\": \"{{ .Values.frontend.reactAppBCeIDKeycloakUrl }}\",\n \"REACT_APP_API_BASE\": + \"{{ .Values.frontend.reactAppApiBase }}\",\n \"REACT_APP_ENV\": + \"{{ .Values.envName }}\"\n};\n" diff --git a/chart/itvr-apps/charts/itvr-frontend/templates/deploymentconfig.yaml b/chart/itvr-apps/charts/itvr-frontend/templates/deploymentconfig.yaml new file mode 100644 index 00000000..42ebddae --- /dev/null +++ b/chart/itvr-apps/charts/itvr-frontend/templates/deploymentconfig.yaml @@ -0,0 +1,82 @@ +kind: DeploymentConfig +apiVersion: apps.openshift.io/v1 +metadata: + annotations: + description: Defines how to deploy the frontend application + name: {{ include "itvr-frontend.deploymentconfigName" . }} + labels: + {{- include "itvr-frontend.labels" . | nindent 4 }} +spec: + strategy: + type: Recreate + recreateParams: + timeoutSeconds: 300 + resources: {} + activeDeadlineSeconds: 600 + triggers: + - type: ImageChange + imageChangeParams: + automatic: true + containerNames: + - frontend + from: + kind: ImageStreamTag + namespace: {{ .Values.image.namespace }} + name: {{ include "itvr-frontend.fullname" . }}:{{ .Values.imageEnv.tag }} + - type: ConfigChange + replicas: 1 + revisionHistoryLimit: 10 + test: false + selector: + {{- include "itvr-frontend.selectorLabels" . | nindent 4 }} + template: + metadata: + creationTimestamp: null + labels: + {{- include "itvr-frontend.labels" . | nindent 8 }} + spec: + volumes: + - name: {{ include "itvr-frontend.configmapName" . }} + configMap: + name: {{ include "itvr-frontend.configmapName" . }} + defaultMode: 420 + containers: + - resources: + limits: + cpu: 60m + memory: 60Mi + requests: + cpu: 30m + memory: 30Mi + readinessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 20 + timeoutSeconds: 3 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 10 + terminationMessagePath: /dev/termination-log + name: frontend + livenessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 30 + timeoutSeconds: 3 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 10 + ports: + - containerPort: 8080 + protocol: TCP + imagePullPolicy: IfNotPresent + volumeMounts: + - name: {{ include "itvr-frontend.configmapName" . }} + mountPath: /app/static/js/config + terminationMessagePolicy: File + restartPolicy: Always + terminationGracePeriodSeconds: 30 + dnsPolicy: ClusterFirst + securityContext: {} + schedulerName: default-scheduler + diff --git a/chart/itvr-apps/charts/itvr-frontend/templates/hpa.yaml b/chart/itvr-apps/charts/itvr-frontend/templates/hpa.yaml new file mode 100644 index 00000000..a099fea9 --- /dev/null +++ b/chart/itvr-apps/charts/itvr-frontend/templates/hpa.yaml @@ -0,0 +1,28 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "itvr-frontend.fullname" . }} + labels: + {{- include "itvr-frontend.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "itvr-frontend.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/chart/itvr-apps/charts/itvr-frontend/templates/imagestream.yaml b/chart/itvr-apps/charts/itvr-frontend/templates/imagestream.yaml new file mode 100644 index 00000000..f6bbb593 --- /dev/null +++ b/chart/itvr-apps/charts/itvr-frontend/templates/imagestream.yaml @@ -0,0 +1,19 @@ +apiVersion: image.openshift.io/v1 +kind: ImageStream +metadata: + labels: + {{- include "itvr-frontend.labels" . | nindent 4 }} + creationTimestamp: null + name: {{ include "itvr-frontend.imagestreamName" . }} +spec: + lookupPolicy: + local: false + tags: + - name: {{ .Values.imageEnv.tag }} + from: + kind: ImageStreamImage + namespace: {{ .Values.toolsNamespace }} + name: {{ .Values.imageTools.tag }} + importPolicy: {} + referencePolicy: + type: Local diff --git a/chart/itvr-apps/charts/itvr-frontend/templates/ingress.yaml b/chart/itvr-apps/charts/itvr-frontend/templates/ingress.yaml new file mode 100644 index 00000000..fce7363a --- /dev/null +++ b/chart/itvr-apps/charts/itvr-frontend/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "itvr-frontend.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "itvr-frontend.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/chart/itvr-apps/charts/itvr-frontend/templates/route.yaml b/chart/itvr-apps/charts/itvr-frontend/templates/route.yaml new file mode 100644 index 00000000..a3406237 --- /dev/null +++ b/chart/itvr-apps/charts/itvr-frontend/templates/route.yaml @@ -0,0 +1,20 @@ +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + name: {{ include "itvr-frontend.routeName" . }} + annotations: + haproxy.router.openshift.io/timeout: 1500s + labels: + {{- include "itvr-frontend.labels" . | nindent 4 }} +spec: + host: {{ include "itvr-frontend.fullname" . }}-{{ .Values.envName }}.apps.silver.devops.gov.bc.ca + port: + targetPort: http + tls: + insecureEdgeTerminationPolicy: Redirect + termination: edge + to: + kind: Service + name: {{ include "itvr-frontend.fullname" . }} + weight: 100 + wildcardPolicy: None \ No newline at end of file diff --git a/chart/itvr-apps/charts/itvr-frontend/templates/service.yaml b/chart/itvr-apps/charts/itvr-frontend/templates/service.yaml new file mode 100644 index 00000000..5c5f7fd9 --- /dev/null +++ b/chart/itvr-apps/charts/itvr-frontend/templates/service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "itvr-frontend.serviceName" . }} + labels: + {{- include "itvr-frontend.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "itvr-frontend.selectorLabels" . | nindent 4 }} + sessionAffinity: None diff --git a/chart/itvr-apps/charts/itvr-frontend/templates/serviceaccount.yaml b/chart/itvr-apps/charts/itvr-frontend/templates/serviceaccount.yaml new file mode 100644 index 00000000..bb9f9f1e --- /dev/null +++ b/chart/itvr-apps/charts/itvr-frontend/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "itvr-frontend.serviceAccountName" . }} + labels: + {{- include "itvr-frontend.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/chart/itvr-apps/charts/itvr-frontend/values-dev.yaml b/chart/itvr-apps/charts/itvr-frontend/values-dev.yaml new file mode 100644 index 00000000..2c784de8 --- /dev/null +++ b/chart/itvr-apps/charts/itvr-frontend/values-dev.yaml @@ -0,0 +1,109 @@ +# Default values for itvr-frontend. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +toolsNamespace: ac294c-tools +envNamespace: ac294c-dev +envName: dev + +# decide which image in tools project will be used +imageTools: + repository: image-registry.openshift-image-registry.svc:5000 + tag: itvr-frontend@sha256:40d75efd2f366efc04d251dbe14bcfcd05a66a93f8419968d72c0596a4965e23 + pullPolicy: IfNotPresent + +# decide the imagestream will be created in env projects +# for pr based, coulde user the value fpr 1.0.0- +imageEnv: + tag: 1.0.0 + +imagePullSecrets: [] + +## For ITVR Frontend App, set the following two, will result in +## itvr-frontend.fullname and itvr-frontend.name are itve-frontend +#nameOverride: "itvr-frontend" +#fullnameOverride: "itvr-frontend" + +nameOverride: "" +fullnameOverride: "" + + +serviceAccount: + # Specifies whether a service account should be created + create: false + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 8080 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 60m + memory: 60Mi + requests: + cpu: 30m + memory: 30Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +frontend: + reactAppBCSCKeycloakClientId: itvr + reactAppBCSCKeycloakRealm: rzh2zkjq + reactAppBCSCKeycloakUrl: https://dev.oidc.gov.bc.ca/auth/ + reactAppApiBase: https://itvr-backend-dev.apps.silver.devops.gov.bc.ca + reactAppBCeIDKeycloakClientId: itvr-2674 + reactAppBCeIDKeycloakRealm: onestopauth-basic + reactAppBCeIDKeycloakUrl: https://dev.oidc.gov.bc.ca/auth/ + + diff --git a/chart/itvr-apps/charts/itvr-frontend/values-prod.yaml b/chart/itvr-apps/charts/itvr-frontend/values-prod.yaml new file mode 100644 index 00000000..ff35ce81 --- /dev/null +++ b/chart/itvr-apps/charts/itvr-frontend/values-prod.yaml @@ -0,0 +1,85 @@ +# Default values for itvr-frontend. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: image-registry.openshift-image-registry.svc:5000/ac294c-tools/itvr-frontend + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "build-1.0.0-205" + +imagePullSecrets: [] + +## For ITVR Frontend App, set the following two, will result in +## itvr-frontend.fullname and itvr-frontend.name are itve-frontend +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: false + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 8080 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/chart/itvr-apps/charts/itvr-frontend/values-test.yaml b/chart/itvr-apps/charts/itvr-frontend/values-test.yaml new file mode 100644 index 00000000..ff35ce81 --- /dev/null +++ b/chart/itvr-apps/charts/itvr-frontend/values-test.yaml @@ -0,0 +1,85 @@ +# Default values for itvr-frontend. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: image-registry.openshift-image-registry.svc:5000/ac294c-tools/itvr-frontend + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "build-1.0.0-205" + +imagePullSecrets: [] + +## For ITVR Frontend App, set the following two, will result in +## itvr-frontend.fullname and itvr-frontend.name are itve-frontend +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: false + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 8080 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/chart/itvr-apps/charts/itvr-frontend/values.yaml b/chart/itvr-apps/charts/itvr-frontend/values.yaml new file mode 100644 index 00000000..3d157bd4 --- /dev/null +++ b/chart/itvr-apps/charts/itvr-frontend/values.yaml @@ -0,0 +1,82 @@ +# Default values for itvr-frontend. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: nginx + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/chart/itvr-clamav/Chart.yaml b/chart/itvr-clamav/Chart.yaml new file mode 100644 index 00000000..df4a8933 --- /dev/null +++ b/chart/itvr-clamav/Chart.yaml @@ -0,0 +1,30 @@ +apiVersion: v2 +name: itvr-clamav +description: A Helm chart for Kubernetes + +# 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: 1.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.105_base" + +## version history +# initial version +# version: 1.0.0 appVersion: "1.105_base" +# add network policies +# version: 1.1.0 appVersion: "1.105_base" diff --git a/chart/itvr-clamav/templates/NOTES.txt b/chart/itvr-clamav/templates/NOTES.txt new file mode 100644 index 00000000..1e00815e --- /dev/null +++ b/chart/itvr-clamav/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "itvr-clamav.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "itvr-clamav.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "itvr-clamav.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "itvr-clamav.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/chart/itvr-clamav/templates/_helpers.tpl b/chart/itvr-clamav/templates/_helpers.tpl new file mode 100644 index 00000000..cf261c9d --- /dev/null +++ b/chart/itvr-clamav/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "itvr-clamav.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 "itvr-clamav.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "itvr-clamav.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "itvr-clamav.labels" -}} +helm.sh/chart: {{ include "itvr-clamav.chart" . }} +{{ include "itvr-clamav.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "itvr-clamav.selectorLabels" -}} +app.kubernetes.io/name: {{ include "itvr-clamav.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "itvr-clamav.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "itvr-clamav.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/chart/itvr-clamav/templates/deployment.yaml b/chart/itvr-clamav/templates/deployment.yaml new file mode 100644 index 00000000..4cafa698 --- /dev/null +++ b/chart/itvr-clamav/templates/deployment.yaml @@ -0,0 +1,76 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "itvr-clamav.fullname" . }} + labels: + {{- include "itvr-clamav.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "itvr-clamav.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "itvr-clamav.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "itvr-clamav.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + volumes: + - name: clamav-signature-db + persistentVolumeClaim: + claimName: clamav-signature-db + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: 3310 + protocol: TCP + readinessProbe: + tcpSocket: + port: 3310 + initialDelaySeconds: 60 + timeoutSeconds: 3 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 20 + livenessProbe: + tcpSocket: + port: 3310 + initialDelaySeconds: 60 + timeoutSeconds: 3 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 20 + volumeMounts: + - name: clamav-signature-db + mountPath: /var/lib/clamav + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/chart/itvr-clamav/templates/hpa.yaml b/chart/itvr-clamav/templates/hpa.yaml new file mode 100644 index 00000000..e7cc1328 --- /dev/null +++ b/chart/itvr-clamav/templates/hpa.yaml @@ -0,0 +1,28 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "itvr-clamav.fullname" . }} + labels: + {{- include "itvr-clamav.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "itvr-clamav.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/chart/itvr-clamav/templates/ingress.yaml b/chart/itvr-clamav/templates/ingress.yaml new file mode 100644 index 00000000..878666c1 --- /dev/null +++ b/chart/itvr-clamav/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "itvr-clamav.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "itvr-clamav.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/chart/itvr-clamav/templates/networkpolicy.yaml b/chart/itvr-clamav/templates/networkpolicy.yaml new file mode 100644 index 00000000..a14c22d4 --- /dev/null +++ b/chart/itvr-clamav/templates/networkpolicy.yaml @@ -0,0 +1,14 @@ +{{- if .Values.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: networking.k8s.io/v1 +metadata: + name: {{ template "itvr-clamav.fullname" . }}-intra-release + labels: {{ include "itvr-clamav.labels" . | nindent 4 }} +spec: + podSelector: + matchLabels: {{ include "itvr-clamav.selectorLabels" . | nindent 6 }} + ingress: + - from: + - podSelector: + matchLabels: {{ include "itvr-clamav.selectorLabels" . | nindent 10 }} +{{- end }} diff --git a/chart/itvr-clamav/templates/pvc.yaml b/chart/itvr-clamav/templates/pvc.yaml new file mode 100644 index 00000000..48706d3e --- /dev/null +++ b/chart/itvr-clamav/templates/pvc.yaml @@ -0,0 +1,13 @@ +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: clamav-signature-db + labels: {{ include "itvr-clamav.labels" . | nindent 4 }} +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1Gi + storageClassName: netapp-file-standard + diff --git a/chart/itvr-clamav/templates/service.yaml b/chart/itvr-clamav/templates/service.yaml new file mode 100644 index 00000000..aaab1793 --- /dev/null +++ b/chart/itvr-clamav/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "itvr-clamav.fullname" . }} + labels: + {{- include "itvr-clamav.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "itvr-clamav.selectorLabels" . | nindent 4 }} diff --git a/chart/itvr-clamav/values-dev.yaml b/chart/itvr-clamav/values-dev.yaml new file mode 100644 index 00000000..ec28026d --- /dev/null +++ b/chart/itvr-clamav/values-dev.yaml @@ -0,0 +1,85 @@ +# Default values for itvr-clamav. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: image-registry.openshift-image-registry.svc:5000/ac294c-tools/itvr-clamav + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "0.105_base" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: false + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 3310 + +networkPolicy: + enabled: false + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 280m + memory: 3Gi + requests: + cpu: 140m + memory: 1Gi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/chart/itvr-clamav/values-prod.yaml b/chart/itvr-clamav/values-prod.yaml new file mode 100644 index 00000000..7fdf2168 --- /dev/null +++ b/chart/itvr-clamav/values-prod.yaml @@ -0,0 +1,85 @@ +# Default values for itvr-clamav. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: image-registry.openshift-image-registry.svc:5000/ac294c-tools/itvr-clamav + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "0.105_base" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: false + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 3310 + +networkPolicy: + enabled: false + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 280m + memory: 2Gi + requests: + cpu: 140m + memory: 1Gi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/chart/itvr-clamav/values-test.yaml b/chart/itvr-clamav/values-test.yaml new file mode 100644 index 00000000..7fdf2168 --- /dev/null +++ b/chart/itvr-clamav/values-test.yaml @@ -0,0 +1,85 @@ +# Default values for itvr-clamav. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: image-registry.openshift-image-registry.svc:5000/ac294c-tools/itvr-clamav + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "0.105_base" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: false + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 3310 + +networkPolicy: + enabled: false + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 280m + memory: 2Gi + requests: + cpu: 140m + memory: 1Gi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/chart/itvr-clamav/values.yaml b/chart/itvr-clamav/values.yaml new file mode 100644 index 00000000..175cc9ee --- /dev/null +++ b/chart/itvr-clamav/values.yaml @@ -0,0 +1,82 @@ +# Default values for itvr-clamav. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: nginx + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/chart/itvr/charts/itvr-minio/Chart.yaml b/chart/itvr-minio/Chart.yaml similarity index 100% rename from chart/itvr/charts/itvr-minio/Chart.yaml rename to chart/itvr-minio/Chart.yaml diff --git a/chart/itvr/charts/itvr-minio/charts/minio-10.1.7.tgz b/chart/itvr-minio/charts/minio-10.1.7.tgz similarity index 100% rename from chart/itvr/charts/itvr-minio/charts/minio-10.1.7.tgz rename to chart/itvr-minio/charts/minio-10.1.7.tgz diff --git a/chart/itvr/charts/itvr-minio/templates/routes.yaml b/chart/itvr-minio/templates/routes.yaml similarity index 100% rename from chart/itvr/charts/itvr-minio/templates/routes.yaml rename to chart/itvr-minio/templates/routes.yaml diff --git a/chart/itvr/charts/itvr-minio/values-dev.yaml b/chart/itvr-minio/values-dev.yaml similarity index 100% rename from chart/itvr/charts/itvr-minio/values-dev.yaml rename to chart/itvr-minio/values-dev.yaml diff --git a/chart/itvr/charts/itvr-minio/values-prod.yaml b/chart/itvr-minio/values-prod.yaml similarity index 100% rename from chart/itvr/charts/itvr-minio/values-prod.yaml rename to chart/itvr-minio/values-prod.yaml diff --git a/chart/itvr/charts/itvr-minio/values-test.yaml b/chart/itvr-minio/values-test.yaml similarity index 100% rename from chart/itvr/charts/itvr-minio/values-test.yaml rename to chart/itvr-minio/values-test.yaml diff --git a/chart/itvr/charts/itvr-minio/values.yaml b/chart/itvr-minio/values.yaml similarity index 100% rename from chart/itvr/charts/itvr-minio/values.yaml rename to chart/itvr-minio/values.yaml diff --git a/chart/itvr-spilo/.helmignore b/chart/itvr-spilo/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/chart/itvr-spilo/.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/chart/itvr/charts/itvr-spilo/Chart.yaml b/chart/itvr-spilo/Chart.yaml similarity index 100% rename from chart/itvr/charts/itvr-spilo/Chart.yaml rename to chart/itvr-spilo/Chart.yaml diff --git a/chart/itvr/charts/itvr-spilo/Readme.md b/chart/itvr-spilo/Readme.md similarity index 100% rename from chart/itvr/charts/itvr-spilo/Readme.md rename to chart/itvr-spilo/Readme.md diff --git a/chart/itvr/charts/itvr-spilo/templates/_helpers.tpl b/chart/itvr-spilo/templates/_helpers.tpl similarity index 100% rename from chart/itvr/charts/itvr-spilo/templates/_helpers.tpl rename to chart/itvr-spilo/templates/_helpers.tpl diff --git a/chart/itvr/charts/itvr-spilo/values-dev.yaml b/chart/itvr-spilo/values-dev.yaml similarity index 100% rename from chart/itvr/charts/itvr-spilo/values-dev.yaml rename to chart/itvr-spilo/values-dev.yaml diff --git a/chart/itvr/charts/itvr-spilo/values-prod.yaml b/chart/itvr-spilo/values-prod.yaml similarity index 100% rename from chart/itvr/charts/itvr-spilo/values-prod.yaml rename to chart/itvr-spilo/values-prod.yaml diff --git a/chart/itvr/charts/itvr-spilo/values-test.yaml b/chart/itvr-spilo/values-test.yaml similarity index 100% rename from chart/itvr/charts/itvr-spilo/values-test.yaml rename to chart/itvr-spilo/values-test.yaml diff --git a/chart/itvr/charts/spilo/Chart.yaml b/chart/spilo/Chart.yaml similarity index 100% rename from chart/itvr/charts/spilo/Chart.yaml rename to chart/spilo/Chart.yaml diff --git a/chart/itvr/charts/spilo/docs/restore.md b/chart/spilo/docs/restore.md similarity index 100% rename from chart/itvr/charts/spilo/docs/restore.md rename to chart/spilo/docs/restore.md diff --git a/chart/itvr/charts/spilo/docs/s3.png b/chart/spilo/docs/s3.png similarity index 100% rename from chart/itvr/charts/spilo/docs/s3.png rename to chart/spilo/docs/s3.png diff --git a/chart/itvr/charts/spilo/templates/_helpers.tpl b/chart/spilo/templates/_helpers.tpl similarity index 100% rename from chart/itvr/charts/spilo/templates/_helpers.tpl rename to chart/spilo/templates/_helpers.tpl diff --git a/chart/itvr/charts/spilo/templates/archive-pvc.yaml b/chart/spilo/templates/archive-pvc.yaml similarity index 100% rename from chart/itvr/charts/spilo/templates/archive-pvc.yaml rename to chart/spilo/templates/archive-pvc.yaml diff --git a/chart/itvr/charts/spilo/templates/networkpolicy.yaml b/chart/spilo/templates/networkpolicy.yaml similarity index 100% rename from chart/itvr/charts/spilo/templates/networkpolicy.yaml rename to chart/spilo/templates/networkpolicy.yaml diff --git a/chart/itvr/charts/spilo/templates/poddisruptionbudget.yaml b/chart/spilo/templates/poddisruptionbudget.yaml similarity index 100% rename from chart/itvr/charts/spilo/templates/poddisruptionbudget.yaml rename to chart/spilo/templates/poddisruptionbudget.yaml diff --git a/chart/itvr/charts/spilo/templates/role.yaml b/chart/spilo/templates/role.yaml similarity index 100% rename from chart/itvr/charts/spilo/templates/role.yaml rename to chart/spilo/templates/role.yaml diff --git a/chart/itvr/charts/spilo/templates/rolebinding.yaml b/chart/spilo/templates/rolebinding.yaml similarity index 100% rename from chart/itvr/charts/spilo/templates/rolebinding.yaml rename to chart/spilo/templates/rolebinding.yaml diff --git a/chart/itvr/charts/spilo/templates/secret.yaml b/chart/spilo/templates/secret.yaml similarity index 100% rename from chart/itvr/charts/spilo/templates/secret.yaml rename to chart/spilo/templates/secret.yaml diff --git a/chart/itvr/charts/spilo/templates/serviceaccount.yaml b/chart/spilo/templates/serviceaccount.yaml similarity index 100% rename from chart/itvr/charts/spilo/templates/serviceaccount.yaml rename to chart/spilo/templates/serviceaccount.yaml diff --git a/chart/itvr/charts/spilo/templates/services.yaml b/chart/spilo/templates/services.yaml similarity index 100% rename from chart/itvr/charts/spilo/templates/services.yaml rename to chart/spilo/templates/services.yaml diff --git a/chart/itvr/charts/spilo/templates/statefulset.yaml b/chart/spilo/templates/statefulset.yaml similarity index 100% rename from chart/itvr/charts/spilo/templates/statefulset.yaml rename to chart/spilo/templates/statefulset.yaml diff --git a/chart/itvr/charts/spilo/values.yaml b/chart/spilo/values.yaml similarity index 100% rename from chart/itvr/charts/spilo/values.yaml rename to chart/spilo/values.yaml diff --git a/django/api/admin.py b/django/api/admin.py index 40f138c5..af5b47b0 100644 --- a/django/api/admin.py +++ b/django/api/admin.py @@ -34,6 +34,7 @@ def has_delete_permission(self, request, obj=None): @admin.register(GoElectricRebateApplication) class GoElectricRebateApplicationAdmin(admin.ModelAdmin): + search_fields = ["drivers_licence", "id", "status"] pass diff --git a/django/api/apps.py b/django/api/apps.py index bf9b64ef..c6595117 100644 --- a/django/api/apps.py +++ b/django/api/apps.py @@ -10,10 +10,15 @@ class ApiConfig(AppConfig): def ready(self): import api.signal_receivers - from api.scheduled_jobs import schedule_get_ncda_redeemed_rebates + import api.monkey_patches.itvr_django_q.cluster + from api.scheduled_jobs import ( + schedule_get_ncda_redeemed_rebates, + schedule_cancel_untouched_household_applications, + ) if settings.RUN_JOBS and "qcluster" in sys.argv: schedule_get_ncda_redeemed_rebates() + schedule_cancel_untouched_household_applications() class ITVRAdminConfig(AdminConfig): diff --git a/django/api/migrations/0008_alter_goelectricrebateapplication_doc1_and_more.py b/django/api/migrations/0008_alter_goelectricrebateapplication_doc1_and_more.py new file mode 100644 index 00000000..93d31948 --- /dev/null +++ b/django/api/migrations/0008_alter_goelectricrebateapplication_doc1_and_more.py @@ -0,0 +1,34 @@ +# Generated by Django 4.0.1 on 2022-07-14 17:08 + +import api.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0007_alter_goelectricrebate_options_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='goelectricrebateapplication', + name='doc1', + field=models.ImageField(blank=True, null=True, upload_to='docs', validators=[api.validators.validate_file_size, api.validators.validate_file_safe]), + ), + migrations.AlterField( + model_name='goelectricrebateapplication', + name='doc2', + field=models.ImageField(blank=True, null=True, upload_to='docs', validators=[api.validators.validate_file_size, api.validators.validate_file_safe]), + ), + migrations.AlterField( + model_name='householdmember', + name='doc1', + field=models.ImageField(blank=True, null=True, upload_to='docs', validators=[api.validators.validate_file_size, api.validators.validate_file_safe]), + ), + migrations.AlterField( + model_name='householdmember', + name='doc2', + field=models.ImageField(blank=True, null=True, upload_to='docs', validators=[api.validators.validate_file_size, api.validators.validate_file_safe]), + ), + ] diff --git a/django/api/models/go_electric_rebate_application.py b/django/api/models/go_electric_rebate_application.py index b1f38032..1c5aa908 100644 --- a/django/api/models/go_electric_rebate_application.py +++ b/django/api/models/go_electric_rebate_application.py @@ -24,6 +24,7 @@ validate_sin, validate_consent, validate_file_size, + validate_file_safe, ) from django_extensions.db.models import TimeStampedModel from django.utils.translation import gettext_lazy as _ @@ -81,7 +82,10 @@ class Status(TextChoices): date_of_birth = DateField(validators=[validate_driving_age], null=True) tax_year = IntegerField(null=True) doc1 = ImageField( - upload_to="docs", blank=True, null=True, validators=[validate_file_size] + upload_to="docs", + blank=True, + null=True, + validators=[validate_file_size, validate_file_safe], ) def doc1_tag(self): @@ -93,7 +97,10 @@ def doc1_tag(self): doc1_tag.short_description = "First Uploaded Document" doc2 = ImageField( - upload_to="docs", blank=True, null=True, validators=[validate_file_size] + upload_to="docs", + blank=True, + null=True, + validators=[validate_file_size, validate_file_safe], ) def doc2_tag(self): diff --git a/django/api/models/household_member.py b/django/api/models/household_member.py index 33949c4e..f446f38c 100644 --- a/django/api/models/household_member.py +++ b/django/api/models/household_member.py @@ -17,6 +17,7 @@ validate_sin, validate_consent, validate_file_size, + validate_file_safe, ) media_storage = get_storage_class()() @@ -40,7 +41,10 @@ class HouseholdMember(TimeStampedModel): bcsc_city = CharField(max_length=250, unique=False, blank=True, null=True) bcsc_postal_code = CharField(max_length=6, unique=False, blank=True, null=True) doc1 = ImageField( - upload_to="docs", blank=True, null=True, validators=[validate_file_size] + upload_to="docs", + blank=True, + null=True, + validators=[validate_file_size, validate_file_safe], ) def doc1_tag(self): @@ -52,7 +56,10 @@ def doc1_tag(self): doc1_tag.short_description = "First Uploaded Document" doc2 = ImageField( - upload_to="docs", blank=True, null=True, validators=[validate_file_size] + upload_to="docs", + blank=True, + null=True, + validators=[validate_file_size, validate_file_safe], ) def doc2_tag(self): diff --git a/django/api/monkey_patches/itvr_django_q/README.md b/django/api/monkey_patches/itvr_django_q/README.md new file mode 100644 index 00000000..ae73c4f8 --- /dev/null +++ b/django/api/monkey_patches/itvr_django_q/README.md @@ -0,0 +1 @@ +For version 1.3.9 of Django Q \ No newline at end of file diff --git a/django/api/monkey_patches/itvr_django_q/cluster.py b/django/api/monkey_patches/itvr_django_q/cluster.py new file mode 100644 index 00000000..f23bdedf --- /dev/null +++ b/django/api/monkey_patches/itvr_django_q/cluster.py @@ -0,0 +1,149 @@ +# Standard +import ast +from datetime import timedelta +from multiprocessing import current_process + +# External +import arrow + +# Django +from django import db +from django.apps.registry import apps + +from django.conf import settings +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ + +# Local +import django_q.tasks +from django_q.brokers import Broker, get_broker +from django_q.conf import ( + Conf, + croniter, + logger, +) +from django_q.models import Schedule + +# module we're overriding: +from django_q import cluster + + +def itvr_scheduler(broker: Broker = None): + """ + Creates a task from a schedule at the scheduled time and schedules next run + """ + if not broker: + broker = get_broker() + cluster.close_old_django_connections() + try: + database_to_use = {"using": Conf.ORM} if not Conf.HAS_REPLICA else {} + with db.transaction.atomic(**database_to_use): + for s in ( + Schedule.objects.select_for_update() + .exclude(repeats=0) + .filter(next_run__lt=timezone.now()) + .filter( + db.models.Q(cluster__isnull=True) | db.models.Q(cluster=Conf.PREFIX) + ) + ): + args = () + kwargs = {} + # get args, kwargs and hook + if s.kwargs: + try: + # eval should be safe here because dict() + kwargs = eval(f"dict({s.kwargs})") + except SyntaxError: + kwargs = {} + if s.args: + args = ast.literal_eval(s.args) + # single value won't eval to tuple, so: + if type(args) != tuple: + args = (args,) + q_options = kwargs.get("q_options", {}) + include_scheduled_run_day_minus_one = kwargs.pop( + "include_scheduled_run_day_minus_one", False + ) + if s.hook: + q_options["hook"] = s.hook + # set up the next run time + if s.schedule_type != s.ONCE: + next_run = arrow.get(s.next_run) + scheduled_run_day_minus_one = ( + next_run - timedelta(days=1) + ).strftime("%Y-%m-%dT00:00:00Z") + + while True: + if s.schedule_type == s.MINUTES: + next_run = next_run.shift(minutes=+(s.minutes or 1)) + elif s.schedule_type == s.HOURLY: + next_run = next_run.shift(hours=+1) + elif s.schedule_type == s.DAILY: + next_run = next_run.shift(days=+1) + elif s.schedule_type == s.WEEKLY: + next_run = next_run.shift(weeks=+1) + elif s.schedule_type == s.MONTHLY: + next_run = next_run.shift(months=+1) + elif s.schedule_type == s.QUARTERLY: + next_run = next_run.shift(months=+3) + elif s.schedule_type == s.YEARLY: + next_run = next_run.shift(years=+1) + elif s.schedule_type == s.CRON: + if not croniter: + raise ImportError( + _( + "Please install croniter to enable cron expressions" + ) + ) + next_run = arrow.get( + croniter(s.cron, cluster.localtime()).get_next() + ) + if Conf.CATCH_UP or next_run > arrow.utcnow(): + break + # arrow always returns a tz aware datetime, and we don't want + # this when we explicitly configured django with USE_TZ=False + s.next_run = ( + next_run.datetime + if settings.USE_TZ + else next_run.datetime.replace(tzinfo=None) + ) + s.repeats += -1 + # send it to the cluster + scheduled_broker = broker + try: + scheduled_broker = get_broker(q_options["broker_name"]) + except: # invalid broker_name or non existing broker with broker_name + pass + q_options["broker"] = scheduled_broker + q_options["group"] = q_options.get("group", s.name or s.id) + kwargs["q_options"] = q_options + if include_scheduled_run_day_minus_one: + args = args + (scheduled_run_day_minus_one,) + s.task = django_q.tasks.async_task(s.func, *args, **kwargs) + # log it + if not s.task: + logger.error( + _( + f"{current_process().name} failed to create a task from schedule [{s.name or s.id}]" + ) + ) + else: + logger.info( + _( + f"{current_process().name} created a task from schedule [{s.name or s.id}]" + ) + ) + # default behavior is to delete a ONCE schedule + if s.schedule_type == s.ONCE: + if s.repeats < 0: + s.delete() + continue + # but not if it has a positive repeats + s.repeats = 0 + # save the schedule + s.save() + except Exception as e: + logger.error(e) + + +cluster.scheduler = itvr_scheduler diff --git a/django/api/scheduled_jobs.py b/django/api/scheduled_jobs.py index b910b79b..20ba0386 100644 --- a/django/api/scheduled_jobs.py +++ b/django/api/scheduled_jobs.py @@ -1,12 +1,29 @@ from django_q.tasks import schedule -from django_q.models import Schedule +from django.db import IntegrityError - -def schedule_exists(func_name): - return Schedule.objects.filter(func__exact=func_name).exists() +# trying to create a schedule with the same name as an already created schedule will raise an IntegrityError def schedule_get_ncda_redeemed_rebates(): - task_name = "api.tasks.check_rebates_redeemed_since" - if not schedule_exists(task_name): - schedule(task_name, None, task_name, schedule_type="D") + try: + schedule( + "api.tasks.check_rebates_redeemed_since", + name="check_rebates_redeemed_since", + schedule_type="C", + cron="00 22 * * *", + include_scheduled_run_day_minus_one=True, + ) + except IntegrityError: + pass + + +def schedule_cancel_untouched_household_applications(): + try: + schedule( + "api.tasks.cancel_untouched_household_applications", + name="cancel_untouched_household_applications", + schedule_type="C", + cron="30 22 * * *", + ) + except IntegrityError: + pass diff --git a/django/api/serializers/household_member.py b/django/api/serializers/household_member.py index c92908df..c376f716 100644 --- a/django/api/serializers/household_member.py +++ b/django/api/serializers/household_member.py @@ -1,4 +1,8 @@ -from rest_framework.serializers import ModelSerializer, SerializerMethodField +from rest_framework.serializers import ( + ModelSerializer, + SerializerMethodField, + ValidationError, +) from api.models.household_member import HouseholdMember from rest_framework.parsers import FormParser, MultiPartParser @@ -9,6 +13,13 @@ class HouseholdMemberApplicationCreateSerializer(ModelSerializer): FormParser, ) + def validate(self, data): + user_id = self.context["request"].user.id + application_user_id = data["application"].user.id + if user_id == application_user_id: + raise ValidationError("spouse cannot be the same as the main applicant") + return data + class Meta: model = HouseholdMember exclude = ["user", "bcsc_address", "bcsc_city", "bcsc_postal_code"] diff --git a/django/api/services/clam_av.py b/django/api/services/clam_av.py new file mode 100644 index 00000000..d8d1cc61 --- /dev/null +++ b/django/api/services/clam_av.py @@ -0,0 +1,6 @@ +from clamd import ClamdNetworkSocket +from ..settings import CLAMD_HOST, CLAMD_PORT + + +def get_clamd_scanner(): + return ClamdNetworkSocket(CLAMD_HOST, CLAMD_PORT) diff --git a/django/api/services/rebate.py b/django/api/services/rebate.py index 12357be7..bda7c99d 100644 --- a/django/api/services/rebate.py +++ b/django/api/services/rebate.py @@ -3,6 +3,7 @@ from datetime import date, timedelta from django.db.models.signals import post_save from api.services.calculate_rebate import RebateType +from django.utils import timezone # gets applications from rebates @@ -58,8 +59,11 @@ def update_application_statuses(rebates, applications): application.status = GoElectricRebateApplication.Status.NOT_APPROVED else: application.status = GoElectricRebateApplication.Status.APPROVED + application.modified = timezone.now() application_objs.append(application) - GoElectricRebateApplication.objects.bulk_update(application_objs, ["status"]) + GoElectricRebateApplication.objects.bulk_update( + application_objs, ["status", "modified"] + ) for application in application_objs: post_save.send( sender=GoElectricRebateApplication, diff --git a/django/api/settings.py b/django/api/settings.py index f3e3743b..9758f08d 100644 --- a/django/api/settings.py +++ b/django/api/settings.py @@ -253,3 +253,7 @@ MESSAGE_TAGS = messages_custom.TAGS RUN_JOBS = os.getenv("RUN_JOBS", False) + +VIRUS_SCANNING_ENABLED = os.getenv("VIRUS_SCANNING_ENABLED", False) +CLAMD_HOST = os.getenv("CLAMD_HOST", "clamav") +CLAMD_PORT = int(os.getenv("CLAMD_PORT", 3310)) diff --git a/django/api/signal_receivers.py b/django/api/signal_receivers.py index 7b1ec91e..d6110542 100644 --- a/django/api/signal_receivers.py +++ b/django/api/signal_receivers.py @@ -20,13 +20,14 @@ def create_application(sender, instance, created, **kwargs): @receiver(household_application_saved, sender=GoElectricRebateApplication) def after_household_application_created(sender, instance, created, **kwargs): - spouse_email = kwargs.get("spouse_email") - async_task( - "api.tasks.send_spouse_initial_message", - spouse_email, - instance.id, - instance.email, - ) + if settings.EMAIL["SEND_EMAIL"]: + spouse_email = kwargs.get("spouse_email") + async_task( + "api.tasks.send_spouse_initial_message", + spouse_email, + instance.id, + instance.email, + ) @receiver(post_save, sender=HouseholdMember) diff --git a/django/api/tasks.py b/django/api/tasks.py index 2ed50e71..2987b987 100644 --- a/django/api/tasks.py +++ b/django/api/tasks.py @@ -11,8 +11,8 @@ from api.models.go_electric_rebate_application import ( GoElectricRebateApplication, ) -from django_q.models import Schedule from datetime import timedelta +from django.db.models.signals import post_save def get_email_service_token() -> str: @@ -324,6 +324,8 @@ def send_cancel(recipient_email, application_id): +

You are encouraged to apply again as an individual if your spouse is unable to complete the household application.

+

Questions?

Please feel free to contact us at ZEVPrograms@gov.bc.ca

@@ -340,13 +342,8 @@ def send_cancel(recipient_email, application_id): # check for newly redeemed rebates -def check_rebates_redeemed_since(iso_ts=None, schedule_func_name=None): - ts = timezone.now().strftime("%Y-%m-%dT00:00:00Z") - if iso_ts: - ts = iso_ts - elif schedule_func_name: - schedule = Schedule.objects.get(func__exact=schedule_func_name) - ts = (schedule.next_run - timedelta(days=2)).strftime("%Y-%m-%dT%H:%M:%SZ") +def check_rebates_redeemed_since(iso_ts=None): + ts = iso_ts if iso_ts else timezone.now().strftime("%Y-%m-%dT00:00:00Z") print("check_rebate_status " + ts) ncda_ids = get_rebates_redeemed_since(ts) print(ncda_ids) @@ -362,3 +359,27 @@ def check_rebates_redeemed_since(iso_ts=None, schedule_func_name=None): status=GoElectricRebateApplication.Status.REDEEMED, modified=timezone.now(), ) + + +# cancels household_initiated applications with a created_time <= (current_time - 28 days) +def cancel_untouched_household_applications(): + + applications_qs = GoElectricRebateApplication.objects.filter( + status=GoElectricRebateApplication.Status.HOUSEHOLD_INITIATED + ).filter(created__lte=timezone.now() - timedelta(days=28)) + + applications = list(applications_qs) + + applications_qs.update( + status=GoElectricRebateApplication.Status.CANCELLED, + modified=timezone.now(), + ) + + for application in applications: + application.status = GoElectricRebateApplication.Status.CANCELLED + post_save.send( + sender=GoElectricRebateApplication, + instance=application, + created=False, + update_fields={"status"}, + ) diff --git a/django/api/validators.py b/django/api/validators.py index eb040b2e..476951ac 100644 --- a/django/api/validators.py +++ b/django/api/validators.py @@ -1,6 +1,8 @@ from datetime import date from dateutil.relativedelta import relativedelta from django.core.exceptions import ValidationError +from api.services.clam_av import get_clamd_scanner +from .settings import VIRUS_SCANNING_ENABLED def validate_driving_age(dob): @@ -58,8 +60,18 @@ def validate_consent(has_consented): # uses max filesize of 5MB def validate_file_size(file): - if file: - max_size = 5242880 - filesize = file.size - if filesize > max_size: - raise ValidationError("File too large.") + max_size = 5242880 + filesize = file.size + if filesize > max_size: + raise ValidationError("File too large.") + + +def validate_file_safe(file): + if VIRUS_SCANNING_ENABLED: + scanner = get_clamd_scanner() + try: + result = scanner.instream(file) + except Exception: + raise ValidationError("Cannot scan file.") + if result and result["stream"][0] == "FOUND": + raise ValidationError("File infected.") diff --git a/django/api/viewsets/application_form.py b/django/api/viewsets/application_form.py index 4b0c6bc0..660a2fe0 100644 --- a/django/api/viewsets/application_form.py +++ b/django/api/viewsets/application_form.py @@ -51,8 +51,8 @@ def partial_update(self, request, pk=None): @action(detail=True, methods=["GET"], url_path="household") def household(self, request, pk=None): application = GoElectricRebateApplication.objects.get(pk=pk) - if application.status == GoElectricRebateApplication.Status.CANCELLED: - error = {"error": "application_cancelled"} + if application.status != GoElectricRebateApplication.Status.HOUSEHOLD_INITIATED: + error = {"error": "application_advanced"} return Response(error, status=status.HTTP_401_UNAUTHORIZED) application_user_id = application.user.id household_user_id = request.user.id diff --git a/django/requirements.txt b/django/requirements.txt index b2e91af1..f8ba8417 100644 --- a/django/requirements.txt +++ b/django/requirements.txt @@ -6,7 +6,9 @@ botocore==1.24.23 certifi==2021.10.8 cffi==1.15.0 charset-normalizer==2.0.12 +clamd==1.0.2 coverage==6.2 +croniter==1.3.5 cryptography==36.0.2 dj-database-url==0.5.0 Django==4.0.1 diff --git a/docker-compose.yml b/docker-compose.yml index 1e4e8170..77c108c4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -61,6 +61,9 @@ services: - SEND_EMAIL - BYPASS_AUTHENTICATION - NCDA_CLIENT_SECRET + - VIRUS_SCANNING_ENABLED=True + - CLAMD_HOST=clamav + - CLAMD_PORT=3310 volumes: - ./django:/api ports: @@ -89,9 +92,11 @@ services: - CHES_EMAIL_URL - SEND_EMAIL - NCDA_CLIENT_SECRET - - RUN_JOBS=TRUE + - RUN_JOBS=True volumes: - ./django:/api depends_on: - db - api + clamav: + image: clamav/clamav diff --git a/frontend/package.json b/frontend/package.json index 3d777150..876ea4d7 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "frontend", - "version": "1.5.0", + "version": "1.6.0", "private": true, "dependencies": { "@date-io/date-fns": "^2.14.0", diff --git a/frontend/public/tracker.js b/frontend/public/tracker.js index dce226d2..3f6763a7 100644 --- a/frontend/public/tracker.js +++ b/frontend/public/tracker.js @@ -21,7 +21,7 @@ if (window.itvr_config && window.itvr_config.REACT_APP_ENV === 'test') { 'https://www2.gov.bc.ca/StaticWebResources/static/sp/sp-2-14-0.js', 'snowplow' ); - var collector = 'spm.apps.gov.bc.ca'; + var collector = 'spt.apps.gov.bc.ca'; window.snowplow('newTracker', 'rt', collector, { appId: 'Snowplow_standalone', cookieLifetime: 86400 * 548, diff --git a/frontend/src/components/BCEIDLogin.js b/frontend/src/components/BCEIDLogin.js index 41285374..c0701f86 100644 --- a/frontend/src/components/BCEIDLogin.js +++ b/frontend/src/components/BCEIDLogin.js @@ -24,7 +24,7 @@ const BCEIDLogin = (props) => { . If you log in with BCeID you will need to upload images of your BC Driver’s Licence {type === 'spouse' && ' or BC Services Card '} and a secondary piece of ID.{' '} - + Learn more about ID requirements. diff --git a/frontend/src/components/DetailsTable.js b/frontend/src/components/DetailsTable.js index 0ab25caa..f0732cf6 100644 --- a/frontend/src/components/DetailsTable.js +++ b/frontend/src/components/DetailsTable.js @@ -50,7 +50,7 @@ const DetailsTable = ({ data }) => { createData('Postal Code:', data.postal_code), createData('Social Insurance Number (SIN):', data.sin), data.drivers_licence && - createData("B.C. Driver's Licence number:", data.drivers_licence), + createData("BC Driver's Licence number:", data.drivers_licence), createData('Tax Year:', data.tax_year), createData( 'Consent to Disclosure and Storage of, and Access to, Personal Information:', diff --git a/frontend/src/components/Footer.js b/frontend/src/components/Footer.js index 18c160b8..23806b81 100644 --- a/frontend/src/components/Footer.js +++ b/frontend/src/components/Footer.js @@ -4,7 +4,7 @@ const Footer = () => {
  • - Home + Home
  • diff --git a/frontend/src/components/Form.js b/frontend/src/components/Form.js index ed5eb714..63ccf580 100644 --- a/frontend/src/components/Form.js +++ b/frontend/src/components/Form.js @@ -25,7 +25,7 @@ import Upload from './upload/Upload'; import Loading from './Loading'; import { useKeycloak } from '@react-keycloak/web'; import InfoTable from './InfoTable'; -import { addTokenFields } from '../keycloak'; +import { addTokenFields, checkBCSC } from '../keycloak'; import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { DatePicker } from '@mui/x-date-pickers/DatePicker'; @@ -54,6 +54,10 @@ const Form = ({ setNumberOfErrors, setErrorsExistCounter }) => { const queryClient = useQueryClient(); const { keycloak } = useKeycloak(); const kcToken = keycloak.tokenParsed; + let bcscMissingFields = []; + if (kcToken.identity_provider === 'bcsc') { + bcscMissingFields = checkBCSC(kcToken); + } const methods = useForm({ defaultValues }); @@ -198,7 +202,7 @@ const Form = ({ setNumberOfErrors, setErrorsExistCounter }) => { secure form submission {kcToken.identity_provider === 'bcsc' ? ( - + ) : ( <> @@ -422,7 +426,7 @@ const Form = ({ setNumberOfErrors, setErrorsExistCounter }) => { {errors?.drivers_licence?.type === 'dlFormat' && ( -

    Not a valid B.C. Driver's Licence Number

    +

    Not a valid BC Driver's Licence Number

    )} {errors?.drivers_licence?.type === 'dlExists' && (

    @@ -504,7 +508,7 @@ const Form = ({ setNumberOfErrors, setErrorsExistCounter }) => { paddingX: '30px', paddingY: '10px' }} - disabled={loading} + disabled={loading || bcscMissingFields.length > 0} > Submit Application diff --git a/frontend/src/components/Header.js b/frontend/src/components/Header.js index b2b94fa5..855a3445 100644 --- a/frontend/src/components/Header.js +++ b/frontend/src/components/Header.js @@ -7,18 +7,10 @@ const Header = ({ logoutUri }) => {

    diff --git a/frontend/src/components/InfoTable.js b/frontend/src/components/InfoTable.js index 88ee4c7d..3b1f68cd 100644 --- a/frontend/src/components/InfoTable.js +++ b/frontend/src/components/InfoTable.js @@ -6,7 +6,11 @@ import TableCell from '@mui/material/TableCell'; import TableContainer from '@mui/material/TableContainer'; import TableRow from '@mui/material/TableRow'; -const InfoTable = ({ householdInfo = {}, kcToken = '' }) => { +const InfoTable = ({ + householdInfo = {}, + kcToken = '', + bcscMissingFields = [] +}) => { function createData(name, answer) { return { name, answer }; } @@ -28,10 +32,18 @@ const InfoTable = ({ householdInfo = {}, kcToken = '' }) => { return ( <> {kcToken && ( -

    - Your name, date of birth and address below has been provided from your - BC Services Card app. -

    +
    +

    + Your name, date of birth and address below has been provided from + your BC Services Card app. +

    + {bcscMissingFields.length > 0 && ( +

    + Your BC Services Card app has provided incomplete information, the + following field(s) are missing: {bcscMissingFields.join(', ')} +

    + )} +
    )} diff --git a/frontend/src/components/Layout.js b/frontend/src/components/Layout.js index 24195423..03968985 100644 --- a/frontend/src/components/Layout.js +++ b/frontend/src/components/Layout.js @@ -7,6 +7,7 @@ const Layout = ({ children, logoutUri }) => { const location = useLocation(); useEffect(() => { if (window.snowplow) { + window.snowplow('refreshLinkClickTracking'); window.snowplow('trackPageView'); } }, [location]); diff --git a/frontend/src/components/Logout.js b/frontend/src/components/Logout.js index 9e686c53..29b6b60c 100644 --- a/frontend/src/components/Logout.js +++ b/frontend/src/components/Logout.js @@ -8,7 +8,7 @@ const Logout = ({ logoutUri }) => { return (
    {'Logged in as: ' + kcToken.display_name + ' |'} - { if (logoutUri) { @@ -18,8 +18,8 @@ const Logout = ({ logoutUri }) => { } }} > -  Log out - + Log out +
    ); } diff --git a/frontend/src/components/SpouseForm.js b/frontend/src/components/SpouseForm.js index 7f42fb4a..9385ffd2 100644 --- a/frontend/src/components/SpouseForm.js +++ b/frontend/src/components/SpouseForm.js @@ -17,7 +17,7 @@ import Upload from './upload/Upload'; import Loading from './Loading'; import { useKeycloak } from '@react-keycloak/web'; import InfoTable from './InfoTable'; -import { addTokenFields } from '../keycloak'; +import { addTokenFields, checkBCSC } from '../keycloak'; import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { DatePicker } from '@mui/x-date-pickers/DatePicker'; @@ -44,7 +44,7 @@ const SpouseForm = ({ setSameUser }) => { const [loading, setLoading] = useState(false); - const [applicationCancelled, setApplicationCancelled] = useState(false); + const [applicationBlocked, setApplicationBlocked] = useState(false); const { keycloak } = useKeycloak(); const kcToken = keycloak.tokenParsed; const queryClient = useQueryClient(); @@ -62,7 +62,10 @@ const SpouseForm = ({ } = methods; const [DOB, setDOB] = useState(new Date()); const axiosInstance = useAxios(); - + let bcscMissingFields = []; + if (kcToken.identity_provider === 'bcsc') { + bcscMissingFields = checkBCSC(kcToken); + } const queryFn = () => axiosInstance.current .get(`/api/application-form/${id}/household`) @@ -82,7 +85,7 @@ const SpouseForm = ({ } else if ( errorResponse && errorResponse.data && - errorResponse.data.error === 'application_cancelled' + errorResponse.data.error === 'application_advanced' ) { return false; } else if (failureCount >= 2) { @@ -148,7 +151,7 @@ const SpouseForm = ({ axiosInstance.current .patch(`/api/application-form/${id}`, { status: 'cancelled' }) .then((response) => { - setApplicationCancelled(true); + setApplicationBlocked(true); setLoading(false); }) .catch((error) => { @@ -159,8 +162,12 @@ const SpouseForm = ({ if (isLoading) { return ; } - if (applicationCancelled) { - return

    This application has been cancelled

    ; + if (applicationBlocked) { + return ( +

    + This application has already been completed, or it has been cancelled. +

    + ); } if (isError) { const errorResponse = error.response; @@ -176,9 +183,9 @@ const SpouseForm = ({ } else if ( errorResponse && errorResponse.data && - errorResponse.data.error === 'application_cancelled' + errorResponse.data.error === 'application_advanced' ) { - setApplicationCancelled(true); + setApplicationBlocked(true); } return

    {error.message}

    ; } @@ -200,7 +207,7 @@ const SpouseForm = ({

    {kcToken.identity_provider === 'bcsc' ? ( - + ) : ( <> @@ -343,7 +350,7 @@ const SpouseForm = ({ paddingX: '30px', paddingY: '10px' }} - disabled={loading} + disabled={loading || bcscMissingFields.length > 0} > Submit Application diff --git a/frontend/src/components/upload/Upload.js b/frontend/src/components/upload/Upload.js index 5694fd67..91981215 100644 --- a/frontend/src/components/upload/Upload.js +++ b/frontend/src/components/upload/Upload.js @@ -25,9 +25,9 @@ const Upload = (props) => {

    - See examples of accepted ID + See examples of accepted ID - (link opens in a new tab to prevent losing form data) +  (link opens in a new tab to prevent losing form data)

    {errors?.documents?.type === 'exactlyTwo' && ( diff --git a/frontend/src/keycloak.js b/frontend/src/keycloak.js index 8757a599..df0ee7d1 100644 --- a/frontend/src/keycloak.js +++ b/frontend/src/keycloak.js @@ -49,3 +49,23 @@ export const addTokenFields = (data, kcToken) => { } return data; }; + +export const checkBCSC = (kcToken) => { + const missingBcscfields = []; + checkField( + 'Your last name (surname)', + kcToken.family_name, + missingBcscfields + ); + checkField('First name (given name)', kcToken.given_name, missingBcscfields); + checkField('Date of birth', kcToken.birthdate, missingBcscfields); + checkField('Street address', kcToken.street_address, missingBcscfields); + checkField('City', kcToken.locality, missingBcscfields); + return missingBcscfields; +}; + +const checkField = (name, answer, missingBcscfields) => { + if (!answer) { + missingBcscfields.push(name); + } +}; diff --git a/frontend/src/styles/Header.scss b/frontend/src/styles/Header.scss index 25e0be70..b3da27fc 100644 --- a/frontend/src/styles/Header.scss +++ b/frontend/src/styles/Header.scss @@ -29,6 +29,10 @@ font-size: 1rem; .logoutButton { cursor: pointer; + border: none; + background: none; + font: inherit; + color: inherit; } } } diff --git a/frontend/src/styles/index.scss b/frontend/src/styles/index.scss index f8c6431e..13d8d95f 100644 --- a/frontend/src/styles/index.scss +++ b/frontend/src/styles/index.scss @@ -122,10 +122,16 @@ a { font-size: 1.5rem; font-weight: normal; + &:focus { + outline: 4px solid #3b99fc; + outline-offset: 5px; + } + &:disabled { color: $grey-dark; background-image: none; opacity: 0.6; + cursor: auto; } } diff --git a/openshift/templates/backend/backend-dc.yaml b/openshift/templates/backend/backend-dc.yaml index 1214e1f1..24ae7e77 100644 --- a/openshift/templates/backend/backend-dc.yaml +++ b/openshift/templates/backend/backend-dc.yaml @@ -6,7 +6,7 @@ metadata: parameters: - name: NAME displayName: null - description: 'the module name entered when run yo bcdk:pipeline, which is itvr' + description: "the module name entered when run yo bcdk:pipeline, which is itvr" required: true - name: SUFFIX displayName: null @@ -19,12 +19,12 @@ parameters: - name: ENV_NAME value: dev displayName: Environment name - description: 'Environment name, dev, test and prod' + description: "Environment name, dev, test and prod" required: true - name: BACKEND_HOST_NAME displayName: Host name for route description: Host name for route - required: true + required: true - name: CPU_REQUEST displayName: Requested CPU description: Requested CPU @@ -42,23 +42,26 @@ parameters: description: Memory upper limit required: true - name: HEALTH_CHECK_DELAY - value: '150' + value: "150" displayName: Memory upper limit description: Memory upper limit - required: true + required: true - name: REPLICAS - value: '1' + value: "1" required: true - name: DJANGO_DEBUG - value: 'False' + value: "False" required: true - name: BUCKET_NAME displayName: bucket name description: bucket name - required: true + required: true - name: CRA_ENVIRONMENT description: the environment for CRA, P for production, A for all other envs required: true + - name: CORS_ORIGIN_WHITELIST + description: CORS_ORIGIN_WHITELIST + required: true objects: - apiVersion: v1 kind: Secret @@ -78,24 +81,24 @@ objects: annotations: description: Keeps track of changes in the backend image labels: - shared: "true" + shared: "true" creationTimestamp: null - name: '${NAME}-backend' + name: "${NAME}-backend" spec: lookupPolicy: local: false status: - dockerImageRepository: '' + dockerImageRepository: "" - apiVersion: v1 kind: Service metadata: creationTimestamp: null - name: '${NAME}-backend${SUFFIX}' -# labels: -# name: backend -# app: itvr -# role: backend -# env: '${ENV_NAME}' + name: "${NAME}-backend${SUFFIX}" + # labels: + # name: backend + # app: itvr + # role: backend + # env: '${ENV_NAME}' spec: ports: - name: backend @@ -103,7 +106,7 @@ objects: protocol: TCP targetPort: 8080 selector: - name: '${NAME}-backend${SUFFIX}' + name: "${NAME}-backend${SUFFIX}" sessionAffinity: None type: ClusterIP status: @@ -111,10 +114,10 @@ objects: - apiVersion: route.openshift.io/v1 kind: Route metadata: - creationTimestamp: - annotations: - haproxy.router.openshift.io/timeout: 1200s - env: '${ENV_NAME}' + creationTimestamp: + annotations: + haproxy.router.openshift.io/timeout: 1200s + env: "${ENV_NAME}" name: ${NAME}-backend${SUFFIX} spec: host: ${BACKEND_HOST_NAME} @@ -126,16 +129,16 @@ objects: termination: edge to: kind: Service - name: '${NAME}-backend${SUFFIX}' + name: "${NAME}-backend${SUFFIX}" weight: 100 wildcardPolicy: None - apiVersion: route.openshift.io/v1 kind: Route metadata: - creationTimestamp: - annotations: - haproxy.router.openshift.io/timeout: 1200s - env: '${ENV_NAME}' + creationTimestamp: + annotations: + haproxy.router.openshift.io/timeout: 1200s + env: "${ENV_NAME}" name: ${NAME}-backend-admin${SUFFIX} spec: host: ${BACKEND_HOST_NAME} @@ -147,16 +150,16 @@ objects: termination: edge to: kind: Service - name: '${NAME}-backend${SUFFIX}' + name: "${NAME}-backend${SUFFIX}" weight: 100 wildcardPolicy: None - apiVersion: route.openshift.io/v1 kind: Route metadata: - creationTimestamp: - annotations: - haproxy.router.openshift.io/timeout: 1200s - env: '${ENV_NAME}' + creationTimestamp: + annotations: + haproxy.router.openshift.io/timeout: 1200s + env: "${ENV_NAME}" name: ${NAME}-backend-static${SUFFIX} spec: host: ${BACKEND_HOST_NAME} @@ -168,31 +171,31 @@ objects: termination: edge to: kind: Service - name: '${NAME}-backend${SUFFIX}' + name: "${NAME}-backend${SUFFIX}" weight: 100 wildcardPolicy: None -# - apiVersion: route.openshift.io/v1 -# kind: Route -# metadata: -# creationTimestamp: null -# labels: -# name: backend -# app: itvr -# role: backend -# env: '${ENV_NAME}' -# name: '${NAME}-backend-health${SUFFIX}' -# spec: -# host: ${HOST_NAME} -# path: /health -# port: -# targetPort: backend -# tls: -# termination: edge -# to: -# kind: Service -# name: '${NAME}-backend${SUFFIX}' -# weight: 100 -# wildcardPolicy: None + # - apiVersion: route.openshift.io/v1 + # kind: Route + # metadata: + # creationTimestamp: null + # labels: + # name: backend + # app: itvr + # role: backend + # env: '${ENV_NAME}' + # name: '${NAME}-backend-health${SUFFIX}' + # spec: + # host: ${HOST_NAME} + # path: /health + # port: + # targetPort: backend + # tls: + # termination: edge + # to: + # kind: Service + # name: '${NAME}-backend${SUFFIX}' + # weight: 100 + # wildcardPolicy: None - apiVersion: apps.openshift.io/v1 kind: DeploymentConfig metadata: @@ -213,7 +216,7 @@ objects: execNewPod: command: - /bin/sh - - '-c' + - "-c" - |- python ./manage.py migrate python ./manage.py createcachetable @@ -236,7 +239,7 @@ objects: - name: ALLOWED_HOSTS value: ${NAME}-backend${SUFFIX}.apps.silver.devops.gov.bc.ca - name: CORS_ORIGIN_WHITELIST - value: "https://${NAME}${SUFFIX}.apps.silver.devops.gov.bc.ca" + value: ${CORS_ORIGIN_WHITELIST} - name: BACKEND_ORIGIN value: https://${NAME}-backend${SUFFIX}.apps.silver.devops.gov.bc.ca - name: DB_ENGINE @@ -275,7 +278,7 @@ objects: valueFrom: secretKeyRef: name: itvr-keycloak - key: BCSC_KEYCLOAK_URL + key: BCSC_KEYCLOAK_URL - name: BCEID_KEYCLOAK_CLIENT_ID valueFrom: secretKeyRef: @@ -290,12 +293,12 @@ objects: valueFrom: secretKeyRef: name: itvr-keycloak - key: BCEID_KEYCLOAK_URL + key: BCEID_KEYCLOAK_URL - name: DJANGO_SECRET_KEY valueFrom: secretKeyRef: name: itvr-django-secret${SUFFIX} - key: DJANGO_SECRET_KEY + key: DJANGO_SECRET_KEY - name: DJANGO_SALT_KEY valueFrom: secretKeyRef: @@ -305,7 +308,7 @@ objects: valueFrom: secretKeyRef: name: itvr-email-service - key: EMAIL_SERVICE_CLIENT_ID + key: EMAIL_SERVICE_CLIENT_ID - name: EMAIL_SERVICE_CLIENT_SECRET valueFrom: secretKeyRef: @@ -315,7 +318,7 @@ objects: valueFrom: secretKeyRef: name: itvr-email-service - key: CHES_AUTH_URL + key: CHES_AUTH_URL - name: CHES_EMAIL_URL valueFrom: secretKeyRef: @@ -325,14 +328,14 @@ objects: valueFrom: secretKeyRef: name: itvr-email-service - key: SENDER_EMAIL + key: SENDER_EMAIL - name: SENDER_NAME valueFrom: secretKeyRef: name: itvr-email-service key: SENDER_NAME - name: SEND_EMAIL - value: 'True' + value: "True" - name: MINIO_ENDPOINT valueFrom: secretKeyRef: @@ -347,12 +350,12 @@ objects: valueFrom: secretKeyRef: name: ${NAME}-object-storage - key: root-password + key: root-password - name: MINIO_BUCKET_NAME - value: ${BUCKET_NAME} + value: ${BUCKET_NAME} - name: NCDA_CLIENT_ID valueFrom: - secretKeyRef: + secretKeyRef: name: itvr-ncda key: NCDA_CLIENT_ID - name: NCDA_CLIENT_SECRET @@ -374,11 +377,17 @@ objects: valueFrom: secretKeyRef: name: itvr-ncda - key: NCDA_SHAREPOINT_URL + key: NCDA_SHAREPOINT_URL - name: CRA_ENVIRONMENT - value: ${CRA_ENVIRONMENT} + value: ${CRA_ENVIRONMENT} - name: DJANGO_DEBUG value: ${DJANGO_DEBUG} + - name: VIRUS_SCANNING_ENABLED + value: "True" + - name: CLAMD_HOST + value: "itvr-clamav" + - name: CLAMD_PORT + value: "3310" livenessProbe: failureThreshold: 30 tcpSocket: diff --git a/openshift/templates/clamav/clamav-dc.yaml b/openshift/templates/clamav/clamav-dc.yaml index e3eeee81..dec5c1ac 100644 --- a/openshift/templates/clamav/clamav-dc.yaml +++ b/openshift/templates/clamav/clamav-dc.yaml @@ -99,10 +99,10 @@ objects: resources: limits: cpu: 500m - memory: 4Gi + memory: 2Gi requests: cpu: 250m - memory: 2Gi + memory: 1Gi terminationMessagePath: /dev/termination-log terminationMessagePolicy: File dnsPolicy: ClusterFirst diff --git a/openshift/templates/knp/knp-diagram.drawio b/openshift/templates/knp/knp-diagram.drawio index cc181c2b..a8ee4419 100644 --- a/openshift/templates/knp/knp-diagram.drawio +++ b/openshift/templates/knp/knp-diagram.drawio @@ -1 +1 @@ -3Vvbcps6FP0aP+IBBMZ+dG5NOmlO0jZNmpczAmRbNiACwpd+/RFGYC6KD05xIJ7OpGgjBOy1l9bWRu6Bc3f9JYD+7BuxkdNTZXvdAxc9VR1pA/Y3NmwSgzJQR4llGmCb23aGH/gP4kaZWyNso7DQkRLiUOwXjRbxPGTRgg0GAVkVu02IU7yrD6eoYvhhQadqfcI2nSXWoS7v7NcIT2fpnRWZn3Fh2pkbwhm0ySpnApc9cB4QQpMjd32OnNh5qV+S667eOJs9WIA8WucCU3u5U7/p3yf3v8evD9/m1+fAlhQ9GWYJnYi/sU08xJ+YblI3IJt5hTdJQGdkSjzoXO6sZwGJPBvF95JZa9fnlhCfGRVmnCNKNxxiGFHCTDPqOvwsWmP6nDv+HQ/V13nrYs1H3jY2vBHSgCzQOXFIsH1OICvsH2Bnqt7hDgtJFFhon0t4lMFgiuiefiDpF3smdwPu+y+IuIgGG9YhQA6keFmMJ8jDcpr12yHHDjh4hwBZwXESEI8iz+6pA4e9x5kZsKNpfATkOEjLVl2W1SrujsOYFuO7mmGKfvhw67sVI3sRPRj6Cf0meB1HwdsALFFA0Xqvy9KzA04dPnlIGm+vckzkplmOhKmtcSergzaJIeeIoXw4LUBNWiit8QLcqM9PJkK/ZsFT+Licyw+qIuDFm/PbLTSZeBWj2sFTjx1bzF2I+fIsDl7M1GHMT7jYthOUUYj/QHM7XgyBT7BHty+jn/X0C6Hr98ZYhSaZxvG7FGRERB9J7gNNSy6t7Ww+2n38+LkuZDIJGexlNLKb/gWnjG4rUGeJNuyU/oAKiia0FkL5GcrpBN0VoQGaXhCatNmWzgwrzvQhizQPi5wpDwVaroGOabmuFLVcMT5Oyy/u/sj+ytSvBzerYfT4FY4fkdShacdj75MJfNzIpb5xczf3bFtHTX7ltmaf7aXjIICbXAeuolVdWqdELUZVumy8el9/dpA8wXsV7k73vpwtrIfx6vXyn9srNJg/TQ5JQToncFlsKofFZq0InL/oz+50cXP7c44f8L35Kq10SasZgI2nme8LQKMYUGmAvRmApf5DvdH428vpkjZHvsQSSgqxxzLbTmkFUIx+UZBFamHoVbVIbc0vr6v5jYs9TKrSO5LljmU3yqgkvaOWpVep+ucTqezIuJAN469UVq2rsq2tpYW4ga5o1v7qx6dEuvmyybv0rDRVsJyyUX0ShpXeZljVL6p1Paz2ZVNtZ0mlJMloNusRRlU7pdqOx8i+Twctx8jgAzJhtZoJozVFAYO4WykbKBJGF2S/goTNaCBhG61ffm2+T8nmxdMfo9vVz/GNLijuCVewVhQst+xJqGCP4++vrGk5MAyx1ZiuH7gWPUadZFiTW3XLJDlkdQGyqe29Zfy0CFeWd7kUMcl786v2LGP1QXmgQXGgxDGVgQ6eFNTSfQb7l9cDTfyCb/YHB/aXS0upYbP5kVDDa7LvI+WtyMDj8k/oE7Vh/jW+gNr31NWPJJLLruuUApWZkWnnBxQNhL4bVHzXLRYoLbCgbq20WyzQKkiG1gy5LIo3n+JjYelLlibYlXKs7Ey/ljXXNFF0b3wNfpGfF97zd8H3Bej7/UVkssQWURT24zLlFfZCCr3YT+N4QLoMJF7BLDmXuYEWvVgMXS+mHTibYMcpmervlhDBVuRlA0Ap5eRBUERWFUEVWVX7DdSRhVhVtdyDLsfEorPIlFJFsNFSGp0uOJlQpJkUqIKjiARGPZxGjyEK/jHn8Uygyk6yy+cAmoQ+djhNHOwtaly77bs3DrScc3jcnCLK2lCcvxcp2AzKrJkD+gBOVjMLJj7QjR3imeH2v4yjfB+GlHxAO116gtJCR7QlRgGiufNYKlfdr7FDJcsfJD8yHWxtJ09dN04XH7W0AM+21+TxGTVDrHr4jP5X2dINyacubeW8Q5AfKqIE8WjQCDYAEB954QxPaKJcNvIdskGB5BO7Tzc+x21GyEK4ND0ZrPTShiDRFvOsGts0WNNn625x+/KvZ83h9bOLXh/noo2Ura9zcyXWOivdN2HJr2eF7173pxetrWf3PXUOMQrDhfQaIdb+DAtaVemrxf02QCAnx1rTCn1arZRlalJMzbYZet7fpzpTqSPQN0ooDQXKslu85oEC78qndz9OS2rZu5/4gcv/AA== \ No newline at end of file +3Vtbe6I6FP01PurHRUQftfY2p9NpZ8ap05fzBYiCAqEheJlff4IE5RI52GJh/PpQsk247LVX9somtOQrZ3OLgWd+RQa0W5JgbFryuCVJoiyJ9F9o2TKLqkiRZY4tg9kOhh/WH8iMArMGlgH9VEeCkE0sL23UketCnaRsAGO0TnebITt9VQ/MYc7wQwd23vpiGcSMrH1FONjvoDU34yuLAvvFAXFnZvBNYKB1wiRft+QrjBCJjpzNFbRD78V+icbdHPl1f2MYuqTMAK37+ih9Vb7Pnn4P356/Lu6uZKMtKtFpVsAO2BMbyIXsjsk2dgM0qFdYE2FiojlygX19sI4wClwDhtcSaOvQ5wEhjxpFalxAQrYMYhAQRE0mcWz2K9xYZJo4/h2eqqOw1njDzrxrbFnDJxgt4RWyEd7dpyyI9E+mv+S9wxzmowDrsMglLMoAnkNS0E+O+oWeSVyA+f4WIgcSvKUdMLQBsVbpeAIsLOf7fgfk6AED7xQgczjOMHIJdI2W1LPpc4w0TI/m4ZEshEGatSqCIOVxt23KtBDftWkR+MMDO9+tKdvT6AHfi+g3szZhFBwHYAUxgZtCl8W/9hh12OTR7rL2OsFEZjITJIxtlTtZ6tVJDCFBDPHTaSGXpIVYGy/ke2n6okH4y8Qv/mS1EJ4lkcOLo/PbA9Bo9kpHtW3NXXqsU3dB6stRGLwWzQ5D9oNjGUaEMvStP0DbnS+EwEOWS3YPo4xaypjr+sIYy9Fkn+PYVVJphEefttCRu91oaGlns7M9hbef6IJmM5/CnkVjf9EPcEptdgZqLNH6dfHMHg/ndxNzZP/zzRsEZODh2yC+6/oBK54ZKRp4O002EjIjbB6G7VrxOK6vK8OX69Fa4ew2bNosPRumMTkeqkWzpthT07pD+tgkys7cTQ8435Qq58DTgL7kSsG+EIulpog+uauknB8369J8/ZwzPUBnfdfiOVPoc3R1V26YrlbEtK4W1c/T1ePHP4K31pS73v26H0y+gOEEthskAd6ZH86yEBXqUgK7oUOMwTbRgU3Nx6c3JR1VcQnn5n396UF0B++dGh8V93a01J+H67frbw83sLd4mZ2yHGic2NzHpnhabJaKwMWrMnXmy/uHnwvr2XrS3tprJVYBn18KeV8AqumAigPsaABm+veVSuOvkNOZ3Bx4bSpnCLBcKpcalStkUe2kEzIvW6hKPlvEtupLXXl941iuhfKpdyAIDVM34iCTegc1p14x75+/KMsO1LGgqh/KslLZLFtbXYuL24Wvt2tFuvoS5rvyWWaqoJqy0vzEDSulzrAqX+BuelgVqam6VVJGJKnVqh5uVNXz2qThMVL0Gq/mGOl9ghKW8koYbgjEFOJmSTY5TRiFo345gk2tQLANNq+/tt/naPvqKpPgYf1zeK9winvcFawe4NWOPREVjGG4F4I2dRv4vqVXltdPXIueo07SL8mtsmWSBLIKB9nY9sFqsJJN70ImYqLnZqMKlrFKL3uiXvpEkWNyJzp5UpAy1+kVL697Xf4DHu0vn9hfyCyl+tXqI24OL8m+z0xvaQael39cn0gV86/yBVTRXedfkrQdOq5RGSjLjH3u/ISiAdd3vZzvmsUCsQYWlK2VNosF+fe8vm5Ch0bx9q94WZh5k9Xl7BA7lzpT7oSuo2kweFK/4F/o59idfue8XwCe11kGGhW2kEC/E5YpbyzXJ8AN/TQMT0hWuM0qmBnnUjeQtBfToeuGtJNHM8u2M6byr+B5sKV5WQFQYlY8cIrIksipIktSp4I6MherfC53gcMw0YkZaO04Ixhw1R5cLjj7RBErKTkPjshLMNLpNJr4EH/TFuFMIAl2tHXkBJr4nmUzmtiWuywxdte3MA66CeewuLlElLt9vn5PU7AalGkzAfQJnMwrC5p8gBM6xNX83b89R9k+jHb0Au1y6SlnFjq8LTGizJs7z5Xl8vs1Dqjs9UPbCzTb0neTp6Kol4uPlFmA77fXJPEZVEOscvgM/jezxR8HXHpqy+oOjj4UeQLxbNBwNgAgD7q+ac1IlLkM6NloC3HbQ0aHbD2Gm4nQkrs0vRislMyGIN7nHvtqbNVgzaf64/Lh9V9XX4C7qQPfJgveRsra17mJEmuZle5RWJLrWe6zl/0Mqrb1bNFdJxAjwF+23wJI23/DglYSO1J6v43MSSfnWtNyfZqvlO2zSVqa7RR60t+XOlNJA7mjZlDqczLLYfGaBEquAKjjXwykgLqygQNWnC8A90FVYeBz9ujnvHy8xpmZ/FU5586KSpy0efjoNnovcPh2Wb7+Dw== \ No newline at end of file diff --git a/openshift/templates/knp/knp-env-pr.yaml b/openshift/templates/knp/knp-env-pr.yaml index 902a7a11..cd6e9535 100644 --- a/openshift/templates/knp/knp-env-pr.yaml +++ b/openshift/templates/knp/knp-env-pr.yaml @@ -68,12 +68,12 @@ objects: - apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: - name: allow-minio-accepts${SUFFIX} + name: allow-clamav-accepts${SUFFIX} spec: ## Allow minio to accept communication from backend podSelector: matchLabels: - app.kubernetes.io/instance: itvr-minio + app.kubernetes.io/instance: itvr-clamav ingress: - from: - podSelector: @@ -81,4 +81,4 @@ objects: name: itvr-backend${SUFFIX} ports: - protocol: TCP - port: 9000 + port: 3310 \ No newline at end of file