From b8110cea6519cecff7ce1b684fac57bc98309d3a Mon Sep 17 00:00:00 2001 From: sylus Date: Sun, 3 Dec 2023 12:57:10 -0500 Subject: [PATCH] feat(rearch): Simplify values and utilize helpers.tpl more --- .github/workflows/release.yml | 4 +- .github/workflows/test.yml | 2 +- .gitignore | 4 + CHANGELOG.md | 4 + LICENSE.md | 2 +- README.md | 11 +- {drupal => charts/drupal}/.helmignore | 3 + {drupal7 => charts/drupal}/Chart.lock | 10 +- {drupal => charts/drupal}/Chart.yaml | 12 +- {drupal => charts/drupal}/README.md | 46 +- {drupal => charts/drupal}/README.md.gotmpl | 8 +- {drupal => charts/drupal}/charts/.gitkeep | 0 .../drupal}/charts/mysql-9.1.7.tgz | Bin .../drupal}/charts/postgresql-11.6.6.tgz | Bin .../drupal}/charts/redis-16.13.2.tgz | Bin charts/drupal/charts/solr-7.5.1.tgz | Bin 0 -> 81748 bytes {drupal => charts/drupal}/conf/nginx.conf | 11 +- .../drupal}/conf/opcache-recommended.ini | 0 {drupal => charts/drupal}/conf/pgbouncer.ini | 0 {drupal => charts/drupal}/conf/php.ini | 0 {drupal => charts/drupal}/conf/proxysql.conf | 0 charts/drupal/conf/settings.d10.php | 1093 +++++++++++++++++ .../drupal}/conf/settings.d9.php | 0 {drupal => charts/drupal}/conf/ssmtp.conf | 0 {drupal => charts/drupal}/conf/userlist.txt | 0 charts/drupal/conf/www.conf | 5 + {drupal => charts/drupal}/templates/NOTES.txt | 9 + charts/drupal/templates/_helpers.tpl | 325 +++++ charts/drupal/templates/cm/drupal.yaml | 40 + .../drupal}/templates/cm/nginx.yaml | 2 +- charts/drupal/templates/cronjob/cron.yaml | 99 ++ .../templates/cronjob/drupal-backup.yaml | 107 ++ charts/drupal/templates/cronjob/drupal.yaml | 90 ++ charts/drupal/templates/deploy/drupal.yaml | 95 ++ .../drupal}/templates/deploy/nginx.yaml | 80 +- .../drupal}/templates/hpa/drupal.yaml | 0 .../drupal}/templates/hpa/nginx.yaml | 0 .../drupal}/templates/ing/drupal.yaml | 26 +- .../job/post-install-site-install.yaml | 188 +++ .../job/post-upgrade-reconfigure.yaml | 109 ++ charts/drupal/templates/netpol/drupal.yaml | 16 + charts/drupal/templates/netpol/route.yaml | 20 + .../templates/pdb/poddisruptionbudget.yaml | 0 .../drupal/templates/pv/csi-azure-file.yaml | 42 + .../templates/pv/csi-azure-shared-disk.yaml | 41 + .../drupal/templates/pvc/csi-azure-file.yaml | 36 + .../templates/pvc/csi-azure-shared-disk.yaml | 36 + .../drupal}/templates/pvc/drupal.yaml | 16 +- charts/drupal/templates/sa/drupal.yaml | 12 + .../drupal}/templates/secret/drupal.yaml | 2 + .../drupal}/templates/secret/pgbouncer.yaml | 0 .../drupal}/templates/secret/proxysql.yaml | 0 .../drupal}/templates/secret/ssmtp.yaml | 0 .../templates/storageclass/csi-azure.yaml | 0 .../drupal}/templates/svc/drupal.yaml | 2 +- .../drupal}/templates/svc/nginx.yaml | 2 +- {drupal => charts/drupal}/values.yaml | 114 +- {solr => charts/solr}/.helmignore | 0 {solr => charts/solr}/Chart.yaml | 0 {solr => charts/solr}/README.md | 0 {drupal7 => charts/solr}/charts/.gitkeep | 0 {solr => charts/solr}/templates/NOTES.txt | 0 {solr => charts/solr}/templates/_helpers.tpl | 0 {solr => charts/solr}/templates/dr/solr.yaml | 0 {solr => charts/solr}/templates/ing/solr.yaml | 0 .../solr}/templates/solrcloud/solr.yaml | 0 {solr => charts/solr}/values.yaml | 0 {drupal7 => charts/varnish}/.helmignore | 1 + charts/varnish/Chart.yaml | 15 + charts/varnish/README.md | 14 + charts/varnish/templates/NOTES.txt | 2 + .../varnish}/templates/_helpers.tpl | 29 +- .../varnish/templates/configmap/varnish.yaml | 32 + charts/varnish/templates/deploy/varnish.yaml | 96 ++ charts/varnish/templates/dr/varnish.yaml | 13 + charts/varnish/templates/secret/varnish.yaml | 15 + .../templates/svc/varnish-headless.yaml | 18 + charts/varnish/templates/svc/varnish.yaml | 15 + charts/varnish/values.yaml | 86 ++ drupal/Chart.lock | 15 - drupal/charts/varnish-0.2.2.tgz | Bin 3538 -> 0 bytes drupal/conf/settings.d8.php | 970 --------------- drupal/conf/varnish.yaml | 0 drupal/conf/www.conf | 9 - drupal/templates/cm/drupal.yaml | 41 - drupal/templates/cronjob/cron.yaml | 232 ---- drupal/templates/cronjob/drupal-backup.yaml | 245 ---- drupal/templates/cronjob/drupal.yaml | 226 ---- drupal/templates/deploy/drupal.yaml | 292 ----- .../job/post-install-site-install.yaml | 362 ------ .../job/post-upgrade-reconfigure.yaml | 279 ----- .../templates/pv/csi-azure-file-backup.yaml | 31 - .../templates/pv/csi-azure-file-private.yaml | 31 - .../templates/pv/csi-azure-file-public.yaml | 31 - drupal/templates/pv/csi-azure-file-tmp.yaml | 31 - .../pv/csi-azure-shared-disk-private.yaml | 31 - .../pv/csi-azure-shared-disk-public.yaml | 31 - .../templates/pvc/csi-azure-file-backup.yaml | 26 - .../templates/pvc/csi-azure-file-private.yaml | 26 - .../templates/pvc/csi-azure-file-public.yaml | 26 - drupal/templates/pvc/csi-azure-file-tmp.yaml | 26 - .../pvc/csi-azure-shared-disk-private.yaml | 26 - .../pvc/csi-azure-shared-disk-public.yaml | 26 - drupal/values-example-csi-azure.yaml | 291 ----- drupal/values-example-single-node.yaml | 23 - drupal7/Chart.yaml | 41 - drupal7/README.md | 291 ----- drupal7/README.md.gotmpl | 166 --- drupal7/charts/mysql-9.1.7.tgz | Bin 44174 -> 0 bytes drupal7/charts/postgresql-11.6.6.tgz | Bin 56646 -> 0 bytes drupal7/charts/redis-16.13.2.tgz | Bin 88770 -> 0 bytes drupal7/charts/varnish-0.2.2.tgz | Bin 3538 -> 0 bytes drupal7/conf/nginx.conf | 96 -- drupal7/conf/opcache-recommended.ini | 5 - drupal7/conf/pgbouncer.ini | 23 - drupal7/conf/php.ini | 12 - drupal7/conf/proxysql.conf | 65 - drupal7/conf/settings.d7.php | 753 ------------ drupal7/conf/ssmtp.conf | 13 - drupal7/conf/userlist.txt | 1 - drupal7/conf/www.conf | 9 - drupal7/templates/NOTES.txt | 100 -- drupal7/templates/_helpers.tpl | 46 - drupal7/templates/cm/drupal.yaml | 32 - drupal7/templates/cm/nginx.yaml | 12 - drupal7/templates/cronjob/cron.yaml | 228 ---- drupal7/templates/cronjob/drupal-backup.yaml | 241 ---- drupal7/templates/cronjob/drupal.yaml | 222 ---- drupal7/templates/deploy/drupal.yaml | 250 ---- drupal7/templates/deploy/nginx.yaml | 98 -- drupal7/templates/hpa/drupal.yaml | 31 - drupal7/templates/hpa/nginx.yaml | 31 - drupal7/templates/ing/drupal.yaml | 68 - .../job/post-install-site-install.yaml | 338 ----- .../job/post-upgrade-reconfigure.yaml | 260 ---- .../templates/pdb/poddisruptionbudget.yaml | 32 - drupal7/templates/pv/azurefile-private.yaml | 22 - drupal7/templates/pv/azurefile-public.yaml | 22 - drupal7/templates/pv/shareddisk-private.yaml | 32 - drupal7/templates/pvc/azurefile-private.yaml | 24 - drupal7/templates/pvc/azurefile-public.yaml | 24 - drupal7/templates/pvc/drupal.yaml | 31 - drupal7/templates/pvc/shareddisk-private.yaml | 24 - drupal7/templates/pvc/shareddisk-public.yaml | 24 - drupal7/templates/secret/drupal.yaml | 24 - drupal7/templates/secret/pgbouncer.yaml | 14 - drupal7/templates/secret/proxysql.yaml | 13 - drupal7/templates/secret/ssmtp.yaml | 12 - .../templates/storageclass/shared-disk.yaml | 20 - drupal7/templates/svc/drupal.yaml | 19 - drupal7/templates/svc/nginx.yaml | 22 - drupal7/values-azurefiles.yaml | 122 -- drupal7/values-kind.yaml | 151 --- drupal7/values.yaml | 765 ------------ solr/charts/.gitkeep | 0 test/config.yaml | 1 - 156 files changed, 2913 insertions(+), 8304 deletions(-) rename {drupal => charts/drupal}/.helmignore (99%) rename {drupal7 => charts/drupal}/Chart.lock (56%) rename {drupal => charts/drupal}/Chart.yaml (79%) rename {drupal => charts/drupal}/README.md (55%) rename {drupal => charts/drupal}/README.md.gotmpl (97%) rename {drupal => charts/drupal}/charts/.gitkeep (100%) rename {drupal => charts/drupal}/charts/mysql-9.1.7.tgz (100%) rename {drupal => charts/drupal}/charts/postgresql-11.6.6.tgz (100%) rename {drupal => charts/drupal}/charts/redis-16.13.2.tgz (100%) create mode 100644 charts/drupal/charts/solr-7.5.1.tgz rename {drupal => charts/drupal}/conf/nginx.conf (92%) rename {drupal => charts/drupal}/conf/opcache-recommended.ini (100%) rename {drupal => charts/drupal}/conf/pgbouncer.ini (100%) rename {drupal => charts/drupal}/conf/php.ini (100%) rename {drupal => charts/drupal}/conf/proxysql.conf (100%) create mode 100644 charts/drupal/conf/settings.d10.php rename {drupal => charts/drupal}/conf/settings.d9.php (100%) rename {drupal => charts/drupal}/conf/ssmtp.conf (100%) rename {drupal => charts/drupal}/conf/userlist.txt (100%) create mode 100644 charts/drupal/conf/www.conf rename {drupal => charts/drupal}/templates/NOTES.txt (96%) create mode 100644 charts/drupal/templates/_helpers.tpl create mode 100644 charts/drupal/templates/cm/drupal.yaml rename {drupal => charts/drupal}/templates/cm/nginx.yaml (84%) create mode 100644 charts/drupal/templates/cronjob/cron.yaml create mode 100644 charts/drupal/templates/cronjob/drupal-backup.yaml create mode 100644 charts/drupal/templates/cronjob/drupal.yaml create mode 100644 charts/drupal/templates/deploy/drupal.yaml rename {drupal => charts/drupal}/templates/deploy/nginx.yaml (64%) rename {drupal => charts/drupal}/templates/hpa/drupal.yaml (100%) rename {drupal => charts/drupal}/templates/hpa/nginx.yaml (100%) rename {drupal => charts/drupal}/templates/ing/drupal.yaml (81%) create mode 100644 charts/drupal/templates/job/post-install-site-install.yaml create mode 100644 charts/drupal/templates/job/post-upgrade-reconfigure.yaml create mode 100644 charts/drupal/templates/netpol/drupal.yaml create mode 100644 charts/drupal/templates/netpol/route.yaml rename {drupal => charts/drupal}/templates/pdb/poddisruptionbudget.yaml (100%) create mode 100644 charts/drupal/templates/pv/csi-azure-file.yaml create mode 100644 charts/drupal/templates/pv/csi-azure-shared-disk.yaml create mode 100644 charts/drupal/templates/pvc/csi-azure-file.yaml create mode 100644 charts/drupal/templates/pvc/csi-azure-shared-disk.yaml rename {drupal => charts/drupal}/templates/pvc/drupal.yaml (74%) create mode 100644 charts/drupal/templates/sa/drupal.yaml rename {drupal => charts/drupal}/templates/secret/drupal.yaml (93%) rename {drupal => charts/drupal}/templates/secret/pgbouncer.yaml (100%) rename {drupal => charts/drupal}/templates/secret/proxysql.yaml (100%) rename {drupal => charts/drupal}/templates/secret/ssmtp.yaml (100%) rename {drupal => charts/drupal}/templates/storageclass/csi-azure.yaml (100%) rename {drupal => charts/drupal}/templates/svc/drupal.yaml (92%) rename {drupal => charts/drupal}/templates/svc/nginx.yaml (97%) rename {drupal => charts/drupal}/values.yaml (90%) rename {solr => charts/solr}/.helmignore (100%) rename {solr => charts/solr}/Chart.yaml (100%) rename {solr => charts/solr}/README.md (100%) rename {drupal7 => charts/solr}/charts/.gitkeep (100%) rename {solr => charts/solr}/templates/NOTES.txt (100%) rename {solr => charts/solr}/templates/_helpers.tpl (100%) rename {solr => charts/solr}/templates/dr/solr.yaml (100%) rename {solr => charts/solr}/templates/ing/solr.yaml (100%) rename {solr => charts/solr}/templates/solrcloud/solr.yaml (100%) rename {solr => charts/solr}/values.yaml (100%) rename {drupal7 => charts/varnish}/.helmignore (97%) create mode 100644 charts/varnish/Chart.yaml create mode 100644 charts/varnish/README.md create mode 100644 charts/varnish/templates/NOTES.txt rename {drupal => charts/varnish}/templates/_helpers.tpl (62%) create mode 100644 charts/varnish/templates/configmap/varnish.yaml create mode 100644 charts/varnish/templates/deploy/varnish.yaml create mode 100755 charts/varnish/templates/dr/varnish.yaml create mode 100644 charts/varnish/templates/secret/varnish.yaml create mode 100644 charts/varnish/templates/svc/varnish-headless.yaml create mode 100644 charts/varnish/templates/svc/varnish.yaml create mode 100644 charts/varnish/values.yaml delete mode 100644 drupal/Chart.lock delete mode 100644 drupal/charts/varnish-0.2.2.tgz delete mode 100644 drupal/conf/settings.d8.php delete mode 100644 drupal/conf/varnish.yaml delete mode 100644 drupal/conf/www.conf delete mode 100644 drupal/templates/cm/drupal.yaml delete mode 100644 drupal/templates/cronjob/cron.yaml delete mode 100644 drupal/templates/cronjob/drupal-backup.yaml delete mode 100644 drupal/templates/cronjob/drupal.yaml delete mode 100644 drupal/templates/deploy/drupal.yaml delete mode 100644 drupal/templates/job/post-install-site-install.yaml delete mode 100644 drupal/templates/job/post-upgrade-reconfigure.yaml delete mode 100644 drupal/templates/pv/csi-azure-file-backup.yaml delete mode 100644 drupal/templates/pv/csi-azure-file-private.yaml delete mode 100644 drupal/templates/pv/csi-azure-file-public.yaml delete mode 100644 drupal/templates/pv/csi-azure-file-tmp.yaml delete mode 100644 drupal/templates/pv/csi-azure-shared-disk-private.yaml delete mode 100644 drupal/templates/pv/csi-azure-shared-disk-public.yaml delete mode 100644 drupal/templates/pvc/csi-azure-file-backup.yaml delete mode 100644 drupal/templates/pvc/csi-azure-file-private.yaml delete mode 100644 drupal/templates/pvc/csi-azure-file-public.yaml delete mode 100644 drupal/templates/pvc/csi-azure-file-tmp.yaml delete mode 100644 drupal/templates/pvc/csi-azure-shared-disk-private.yaml delete mode 100644 drupal/templates/pvc/csi-azure-shared-disk-public.yaml delete mode 100644 drupal/values-example-csi-azure.yaml delete mode 100644 drupal/values-example-single-node.yaml delete mode 100644 drupal7/Chart.yaml delete mode 100644 drupal7/README.md delete mode 100644 drupal7/README.md.gotmpl delete mode 100644 drupal7/charts/mysql-9.1.7.tgz delete mode 100644 drupal7/charts/postgresql-11.6.6.tgz delete mode 100644 drupal7/charts/redis-16.13.2.tgz delete mode 100644 drupal7/charts/varnish-0.2.2.tgz delete mode 100644 drupal7/conf/nginx.conf delete mode 100644 drupal7/conf/opcache-recommended.ini delete mode 100644 drupal7/conf/pgbouncer.ini delete mode 100644 drupal7/conf/php.ini delete mode 100644 drupal7/conf/proxysql.conf delete mode 100644 drupal7/conf/settings.d7.php delete mode 100644 drupal7/conf/ssmtp.conf delete mode 100644 drupal7/conf/userlist.txt delete mode 100644 drupal7/conf/www.conf delete mode 100644 drupal7/templates/NOTES.txt delete mode 100644 drupal7/templates/_helpers.tpl delete mode 100644 drupal7/templates/cm/drupal.yaml delete mode 100644 drupal7/templates/cm/nginx.yaml delete mode 100644 drupal7/templates/cronjob/cron.yaml delete mode 100644 drupal7/templates/cronjob/drupal-backup.yaml delete mode 100644 drupal7/templates/cronjob/drupal.yaml delete mode 100644 drupal7/templates/deploy/drupal.yaml delete mode 100644 drupal7/templates/deploy/nginx.yaml delete mode 100644 drupal7/templates/hpa/drupal.yaml delete mode 100644 drupal7/templates/hpa/nginx.yaml delete mode 100644 drupal7/templates/ing/drupal.yaml delete mode 100644 drupal7/templates/job/post-install-site-install.yaml delete mode 100644 drupal7/templates/job/post-upgrade-reconfigure.yaml delete mode 100644 drupal7/templates/pdb/poddisruptionbudget.yaml delete mode 100644 drupal7/templates/pv/azurefile-private.yaml delete mode 100644 drupal7/templates/pv/azurefile-public.yaml delete mode 100644 drupal7/templates/pv/shareddisk-private.yaml delete mode 100644 drupal7/templates/pvc/azurefile-private.yaml delete mode 100644 drupal7/templates/pvc/azurefile-public.yaml delete mode 100644 drupal7/templates/pvc/drupal.yaml delete mode 100644 drupal7/templates/pvc/shareddisk-private.yaml delete mode 100644 drupal7/templates/pvc/shareddisk-public.yaml delete mode 100644 drupal7/templates/secret/drupal.yaml delete mode 100644 drupal7/templates/secret/pgbouncer.yaml delete mode 100644 drupal7/templates/secret/proxysql.yaml delete mode 100644 drupal7/templates/secret/ssmtp.yaml delete mode 100644 drupal7/templates/storageclass/shared-disk.yaml delete mode 100644 drupal7/templates/svc/drupal.yaml delete mode 100644 drupal7/templates/svc/nginx.yaml delete mode 100644 drupal7/values-azurefiles.yaml delete mode 100644 drupal7/values-kind.yaml delete mode 100644 drupal7/values.yaml delete mode 100644 solr/charts/.gitkeep diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9ca86133..b6051e02 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,7 +3,7 @@ name: Release Charts on: push: branches: - - master + - main # Environment variables available to all jobs and steps in this workflow env: @@ -81,7 +81,7 @@ jobs: - name: Run chart-releaser uses: helm/chart-releaser-action@v1.4.0 with: - charts_dir: . + charts_dir: ./charts env: CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" CR_SKIP_EXISTING: 'true' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7c3a0082..3ba713d5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,7 +2,7 @@ name: Test Helm Charts on: pull_request: branches: - - master + - main # Environment variables available to all jobs and steps in this workflow env: diff --git a/.gitignore b/.gitignore index e0008230..b62c04c7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ packages index.yaml + +tpl/ +!values-example-*.yaml +values-*.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index 161bccca..a76dfbd8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.0 + +- Breaking Changes + ## 0.20.1-beta3 - Enable all of the WxT extension modules for default site install (drupal.extensions.enabled) diff --git a/LICENSE.md b/LICENSE.md index 8fb31687..2d75441b 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ ## MIT License -Copyright (c) 2022 Drupal WxT +Copyright (c) 2023 Drupal WxT Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 79e5e130..c8832e1b 100644 --- a/README.md +++ b/README.md @@ -8,18 +8,18 @@ This chart will deploy a highly available and performant enterprise Drupal site - MySQL configured with ProxySQL - PostgreSQL configured with PGBouncer - Redis +- Solr - Varnish Please consult our **Architectural Diagram** for a recommended setup on Azure: -- **[Architectural Diagram][architectural_diagram]** +- **[Architectural Diagram][diagram]** ## Individual Charts Further documentation can be found at the individual chart level: -- **[Drupal 9][drupal9]** -- **[Drupal 7][drupal7]** +- **[Drupal 9/10][drupal]** ## Development @@ -29,8 +29,7 @@ You can consult the `values.yaml` file for the full range of options available t > **Note:** We try out best to follow `https://semver.org` so that it's clear patch, minor and major releases for breaking changes. -[architectural_diagram]: https://github.com/drupalwxt/helm-drupal/blob/master/docs/diagram-drupal.pdf -[drupal7]: drupal7/README.md -[drupal9]: drupal/README.md +[diagram]: https://github.com/drupalwxt/helm-drupal/blob/master/docs/diagram-drupal.pdf +[drupal]: drupal/README.md [helm]: https://helm.sh/ [wxt]: https://drupalwxt.github.io diff --git a/drupal/.helmignore b/charts/drupal/.helmignore similarity index 99% rename from drupal/.helmignore rename to charts/drupal/.helmignore index f0c13194..b6a3eb5b 100644 --- a/drupal/.helmignore +++ b/charts/drupal/.helmignore @@ -2,6 +2,7 @@ # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store + # Common VCS dirs .git/ .gitignore @@ -10,11 +11,13 @@ .hg/ .hgignore .svn/ + # Common backup files *.swp *.bak *.tmp *~ + # Various IDEs .project .idea/ diff --git a/drupal7/Chart.lock b/charts/drupal/Chart.lock similarity index 56% rename from drupal7/Chart.lock rename to charts/drupal/Chart.lock index 8e355963..84f6585d 100644 --- a/drupal7/Chart.lock +++ b/charts/drupal/Chart.lock @@ -8,8 +8,8 @@ dependencies: - name: redis repository: https://charts.bitnami.com/bitnami version: 16.13.2 -- name: varnish - repository: https://statcan.github.io/charts - version: 0.2.2 -digest: sha256:eff9b22832514728f66d261ff5cac8a31b399b52171bf06c821fdf5fca3f7fb3 -generated: "2023-01-16T08:45:02.67443-05:00" +- name: solr + repository: https://charts.bitnami.com/bitnami + version: 7.5.1 +digest: sha256:e15fab8d13baf578d5c6a36fa9a9cc1d852be8de47ed68064852c56e1512fc6b +generated: "2023-12-02T22:05:14.382491-05:00" diff --git a/drupal/Chart.yaml b/charts/drupal/Chart.yaml similarity index 79% rename from drupal/Chart.yaml rename to charts/drupal/Chart.yaml index be1e34b4..213cc994 100644 --- a/drupal/Chart.yaml +++ b/charts/drupal/Chart.yaml @@ -1,9 +1,9 @@ name: drupal apiVersion: v2 type: application -version: 0.20.1-beta8 +version: 1.0.0 appVersion: 5.0.1 -description: Drupal 8/9 variant of the Web Experience Toolkit (WxT). +description: Drupal 9/10 variant of the Web Experience Toolkit (WxT). keywords: - drupal - cms @@ -35,7 +35,7 @@ dependencies: version: 16.13.2 repository: https://charts.bitnami.com/bitnami condition: redis.enabled - - name: varnish - version: 0.2.2 - repository: https://statcan.github.io/charts - condition: varnish.enabled + - name: solr + version: 7.5.1 + repository: https://charts.bitnami.com/bitnami + condition: solr.enabled diff --git a/drupal/README.md b/charts/drupal/README.md similarity index 55% rename from drupal/README.md rename to charts/drupal/README.md index 396f4c24..24da85f9 100644 --- a/drupal/README.md +++ b/charts/drupal/README.md @@ -1,8 +1,8 @@ # drupal -![Version: 0.20.1-beta7](https://img.shields.io/badge/Version-0.20.1--beta7-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 4.5.3](https://img.shields.io/badge/AppVersion-4.5.3-informational?style=flat-square) +![Version: 1.0.0](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 5.0.1](https://img.shields.io/badge/AppVersion-5.0.1-informational?style=flat-square) -Drupal 8/9 variant of the Web Experience Toolkit (WxT). +Drupal 9/10 variant of the Web Experience Toolkit (WxT). **Homepage:** @@ -24,12 +24,12 @@ Drupal 8/9 variant of the Web Experience Toolkit (WxT). | https://charts.bitnami.com/bitnami | mysql | 9.1.7 | | https://charts.bitnami.com/bitnami | postgresql | 11.6.6 | | https://charts.bitnami.com/bitnami | redis | 16.13.2 | -| https://statcan.github.io/charts | varnish | 0.2.2 | +| https://charts.bitnami.com/bitnami | solr | 7.5.1 | ## Prerequisites -- Kubernetes 1.7+ -- Helm v3.0.0+ +- Kubernetes 1.21+ +- Helm v3.10.0+ ## Installing the Chart @@ -48,8 +48,7 @@ Optionally you can git clone the helm chart and select the appropriate values fi ```sh git clone https://github.com/drupalwxt/helm-drupal cd helm-drupal/drupal -cp values-azurefile.yaml values-override.yaml -helm install --name drupal -f values-override.yaml +helm install --name drupal -f values-.yaml ``` ## Ingress @@ -67,6 +66,7 @@ helm install --name drupal -f values-override.yaml | Key | Type | Default | Description | |-----|------|---------|-------------| | drupal.additionalCrons | object | `{}` | | +| drupal.args | list | `[]` | | | drupal.autoscaling.enabled | bool | `false` | | | drupal.autoscaling.maxReplicas | int | `11` | | | drupal.autoscaling.minReplicas | int | `1` | | @@ -79,16 +79,18 @@ helm install --name drupal -f values-override.yaml | drupal.backup.sqlDumpArgs | string | `""` | | | drupal.backup.volume | object | `{}` | | | drupal.cacheRebuildBeforeDatabaseMigration | bool | `true` | | +| drupal.command | list | `[]` | | | drupal.configSplit.enabled | bool | `false` | | | drupal.configSync.directory | string | `"/private/config/sync"` | | | drupal.cron.enabled | bool | `true` | | +| drupal.cron.failedJobsHistoryLimit | int | `1` | | +| drupal.cron.preInstallScripts | string | `""` | | | drupal.cron.schedule | string | `"0 * * * *"` | | +| drupal.cron.successfulJobsHistoryLimit | int | `3` | | | drupal.dbAvailabilityScript | string | `"until drush sql:query 'SHOW TABLES;'; do echo Waiting for DB; sleep 3; done\necho DB available"` | default script used to detect when the DB is ready | | drupal.disableDefaultFilesMount | bool | `false` | | | drupal.extensions.enabled | bool | `true` | | -| drupal.extraInstallScripts | string | `""` | | | drupal.extraSettings | string | `""` | | -| drupal.extraUpgradeScripts | string | `""` | | | drupal.healthcheck.enabled | bool | `true` | | | drupal.image | string | `"drupalwxt/site-wxt"` | | | drupal.imagePullPolicy | string | `"IfNotPresent"` | | @@ -99,8 +101,13 @@ helm install --name drupal -f values-override.yaml | drupal.persistence.annotations | object | `{}` | | | drupal.persistence.enabled | bool | `false` | | | drupal.persistence.size | string | `"8Gi"` | | +| drupal.php.fpm | string | `"pm.max_children = 50\npm.start_servers = 5\npm.min_spare_servers = 5\npm.max_spare_servers = 35"` | | | drupal.php.ini | object | `{}` | | | drupal.podAnnotations | object | `{}` | | +| drupal.postInstallScripts | string | `""` | | +| drupal.postUpgradeScripts | string | `""` | | +| drupal.preInstallScripts | string | `""` | | +| drupal.preUpgradeScripts | string | `""` | | | drupal.profile | string | `"wxt"` | | | drupal.reconfigure | bool | `true` | | | drupal.replicas | int | `1` | | @@ -112,9 +119,11 @@ helm install --name drupal -f values-override.yaml | drupal.restore.name | string | `"latest"` | | | drupal.restore.suppressTarErrors | bool | `false` | | | drupal.restore.volume | object | `{}` | | -| drupal.securityContext.fsGroup | int | `82` | | -| drupal.securityContext.runAsGroup | int | `82` | | -| drupal.securityContext.runAsUser | int | `82` | | +| drupal.securityContext | object | `{}` | | +| drupal.serviceAccount.annotations | object | `{}` | | +| drupal.serviceAccount.automountServiceAccountToken | bool | `true` | | +| drupal.serviceAccount.create | bool | `true` | | +| drupal.serviceAccount.name | string | `""` | | | drupal.serviceType | string | `"ClusterIP"` | | | drupal.services | string | `""` | | | drupal.siteEmail | string | `"admin@example.com"` | | @@ -127,6 +136,7 @@ helm install --name drupal -f values-override.yaml | drupal.smtp.host | string | `"mail"` | | | drupal.smtp.starttls | bool | `true` | | | drupal.smtp.tls | bool | `true` | | +| drupal.theme | string | `"theme-gcweb"` | | | drupal.tolerations | list | `[]` | | | drupal.updateDBBeforeDatabaseMigration | bool | `true` | | | drupal.username | string | `"admin"` | | @@ -134,8 +144,6 @@ helm install --name drupal -f values-override.yaml | drupal.volumeMounts | string | `nil` | | | drupal.volumePermissions.enabled | bool | `false` | | | drupal.volumes | string | `nil` | | -| drupal.wxtTheme | string | `"theme-gcweb"` | | -| drupal.wxtUpdate | bool | `false` | | ## Nginx @@ -155,8 +163,8 @@ helm install --name drupal -f values-override.yaml | nginx.real_ip_header | string | `"X-Forwarded-For"` | | | nginx.replicas | int | `1` | | | nginx.resolver | string | `"kube-dns.kube-system.svc.cluster.local"` | | -| nginx.securityContext.enabled | bool | `true` | | -| nginx.securityContext.fsGroup | int | `33` | | +| nginx.resources | object | `{}` | | +| nginx.securityContext | object | `{}` | | | nginx.serviceType | string | `"ClusterIP"` | | | nginx.tolerations | list | `[]` | | | nginx.volumeMounts | string | `nil` | | @@ -172,7 +180,7 @@ helm install --name drupal -f values-override.yaml | mysql.auth.username | string | `"wxt"` | | | mysql.enabled | bool | `true` | | | mysql.image.tag | string | `"8.0.29-debian-11-r3"` | | -| mysql.primary.configuration | string | `"[mysqld]\ndefault_authentication_plugin=mysql_native_password\nskip-name-resolve\nexplicit_defaults_for_timestamp\nbasedir=/opt/bitnami/mysql\nplugin_dir=/opt/bitnami/mysql/lib/plugin\nport=3306\nsocket=/opt/bitnami/mysql/tmp/mysql.sock\ndatadir=/bitnami/mysql/data\ntmpdir=/opt/bitnami/mysql/tmp\nmax_allowed_packet=16M\nbind-address=0.0.0.0\npid-file=/opt/bitnami/mysql/tmp/mysqld.pid\nlog-error=/opt/bitnami/mysql/logs/mysqld.log\ncharacter-set-server=UTF8\ncollation-server=utf8_general_ci\nslow_query_log=0\nslow_query_log_file=/opt/bitnami/mysql/logs/mysqld.log\nlong_query_time=10.0\n\nmax_allowed_packet = 256M\ninnodb_buffer_pool_size = 4096M\ninnodb_buffer_pool_instances = 4\ntable_definition_cache = 4096\ntable_open_cache = 8192\ninnodb_flush_log_at_trx_commit=2\n[client]\nport=3306\nsocket=/opt/bitnami/mysql/tmp/mysql.sock\ndefault-character-set=UTF8\nplugin_dir=/opt/bitnami/mysql/lib/plugin\n[manager]\nport=3306\nsocket=/opt/bitnami/mysql/tmp/mysql.sock\npid-file=/opt/bitnami/mysql/tmp/mysqld.pid"` | | +| mysql.primary.configuration | string | `"[mysqld]\ndefault_authentication_plugin=mysql_native_password\nskip-name-resolve\nexplicit_defaults_for_timestamp\nbasedir=/opt/bitnami/mysql\nplugin_dir=/opt/bitnami/mysql/lib/plugin\nport=3306\nsocket=/opt/bitnami/mysql/tmp/mysql.sock\ndatadir=/bitnami/mysql/data\ntmpdir=/opt/bitnami/mysql/tmp\nmax_allowed_packet=16M\nbind-address=0.0.0.0\npid-file=/opt/bitnami/mysql/tmp/mysqld.pid\nlog-error=/opt/bitnami/mysql/logs/mysqld.log\ncharacter-set-server=UTF8\ncollation-server=utf8_general_ci\nslow_query_log=0\nslow_query_log_file=/opt/bitnami/mysql/logs/mysqld.log\nlong_query_time=10.0\ntransaction_isolation=\"READ-COMMITTED\"\n\nmax_allowed_packet = 256M\ninnodb_buffer_pool_size = 4096M\ninnodb_buffer_pool_instances = 4\ntable_definition_cache = 4096\ntable_open_cache = 8192\ninnodb_flush_log_at_trx_commit=2\n\n[client]\nport=3306\nsocket=/opt/bitnami/mysql/tmp/mysql.sock\ndefault-character-set=UTF8\nplugin_dir=/opt/bitnami/mysql/lib/plugin\n\n[manager]\nport=3306\nsocket=/opt/bitnami/mysql/tmp/mysql.sock\npid-file=/opt/bitnami/mysql/tmp/mysqld.pid"` | | | mysql.primary.persistence.enabled | bool | `true` | | | mysql.primary.persistence.size | string | `"128Gi"` | | | mysql.volumePermissions.enabled | bool | `true` | | @@ -284,7 +292,7 @@ helm install --name drupal -f values-override.yaml | varnish.service.port | int | `80` | | | varnish.service.type | string | `"ClusterIP"` | | | varnish.tolerations | list | `[]` | | -| varnish.varnishConfigContent | string | `"vcl 4.0;\n\nimport std;\nimport directors;\n\nbackend nginx {\n .host = \"{{ include \"backend.fullname\" . }}-nginx\";\n .host_header = \"{{ include \"backend.fullname\" . }}-nginx\";\n .port = \"80\";\n}\n\nsub vcl_init {\n new backends = directors.round_robin();\n backends.add_backend(nginx);\n}\n\nsub vcl_recv {\n set req.http.X-Forwarded-Host = req.http.Host;\n if (!req.http.X-Forwarded-Proto) {\n set req.http.X-Forwarded-Proto = \"http\";\n }\n\n # Answer healthcheck\n if (req.url == \"/_healthcheck\" || req.url == \"/healthcheck.txt\") {\n return (synth(700, \"HEALTHCHECK\"));\n }\n set req.backend_hint = backends.backend();\n\n # Answer healthcheck\n if (req.url == \"/_healthcheck\" || req.url == \"/healthcheck.txt\") {\n return (synth(700, \"HEALTHCHECK\"));\n }\n set req.backend_hint = backends.backend();\n\n # Always cache certain file types\n # Remove cookies that Drupal doesn't care about\n if (req.url ~ \"(?i)\\.(asc|dat|tgz|png|gif|jpeg|jpg|ico|swf|css|js)(\\?.*)?$\") {\n unset req.http.Cookie;\n } else if (req.http.Cookie) {\n set req.http.Cookie = \";\" + req.http.Cookie;\n set req.http.Cookie = regsuball(req.http.Cookie, \"; +\", \";\");\n set req.http.Cookie = regsuball(req.http.Cookie, \";(SESS[a-z0-9]+|SSESS[a-z0-9]+|NO_CACHE)=\", \"; \\1=\");\n set req.http.Cookie = regsuball(req.http.Cookie, \";[^ ][^;]*\", \"\");\n set req.http.Cookie = regsuball(req.http.Cookie, \"^[; ]+|[; ]+$\", \"\");\n if (req.http.Cookie == \"\") {\n unset req.http.Cookie;\n } else {\n return (pass);\n }\n }\n # If POST, PUT or DELETE, then don't cache\n if (req.method == \"POST\" || req.method == \"PUT\" || req.method == \"DELETE\") {\n return (pass);\n }\n # Happens before we check if we have this in cache already.\n #\n # Typically you clean up the request here, removing cookies you don't need,\n # rewriting the request, etc.\n return (hash);\n #return (pass);\n}\n\nsub vcl_backend_fetch {\n # NEW\n set bereq.http.Host = \"{{ include \"backend.fullname\" . }}-nginx\";\n\n # Don't add 127.0.0.1 to X-Forwarded-For\n set bereq.http.X-Forwarded-For = regsub(bereq.http.X-Forwarded-For, \"(, )?127\\.0\\.0\\.1$\", \"\");\n}\n\nsub vcl_backend_response {\n if (beresp.http.Location) {\n set beresp.http.Location = regsub(\n beresp.http.Location,\n \"^https?://[^/]+/\",\n bereq.http.X-Forwarded-Proto + \"://\" + bereq.http.X-Forwarded-Host + \"/\"\n );\n }\n # Only cache select response codes\n if (beresp.status == 200 || beresp.status == 203 || beresp.status == 204 || beresp.status == 206 || beresp.status == 300 || beresp.status == 301 || beresp.status == 404 || beresp.status == 405 || beresp.status == 410 || beresp.status == 414 || beresp.status == 501) {\n # Cache for 5 minutes\n set beresp.ttl = 5m;\n set beresp.grace = 12h;\n set beresp.keep = 24h;\n } else {\n set beresp.ttl = 0s;\n }\n}\n\nsub vcl_deliver {\n # Remove identifying information\n unset resp.http.Server;\n unset resp.http.X-Powered-By;\n unset resp.http.X-Varnish;\n unset resp.http.Via;\n\n # Comment these for easier Drupal cache tag debugging in development.\n unset resp.http.Cache-Tags;\n unset resp.http.X-Drupal-Cache-Contexts;\n\n # Add Content-Security-Policy\n # set resp.http.Content-Security-Policy = \"default-src 'self' *.example.ca *.example.ca; style-src 'self' 'unsafe-inline' *.example.ca https://fonts.googleapis.com; script-src 'self' 'unsafe-inline' 'unsafe-eval' *.example.ca *.adobedtm.com use.fontawesome.com blob:; connect-src 'self' *.example.ca *.omtrdc.net *.demdex.net *.everesttech.net; img-src 'self' *.example.ca *.omtrdc.net *.demdex.net *.everesttech.net data:; font-src 'self' *.example.ca https://fonts.gstatic.com\";\n\n # Add CORS Headers\n # if (req.http.Origin ~ \"(?i)\\.example\\.ca$\") {\n # if (req.url ~ \"\\.(ttd|woff|woff2)(\\?.*)?$\") {\n # set resp.http.Access-Control-Allow-Origin = \"*\";\n # set resp.http.Access-Control-Allow-Methods = \"GET\";\n # }\n # }\n\n # Add X-Frame-Options\n if (req.url ~ \"^/livechat\" || req.url ~ \"^/(en/|fr/)?entity-browser/\") {\n set resp.http.X-Frame-Options = \"SAMEORIGIN\";\n } else {\n set resp.http.X-Frame-Options = \"DENY\";\n }\n\n set resp.http.X-Content-Type-Options = \"nosniff\";\n set resp.http.X-XSS-Protection = \"1; mode=block\";\n\n # Happens when we have all the pieces we need, and are about to send the\n # response to the client.\n #\n # You can do accounting or modifying the final object here.\n if (obj.hits > 0) {\n set resp.http.X-Cache = \"HIT\";\n } else {\n set resp.http.X-Cache = \"MISS\";\n }\n # Handle errors\n if ( (resp.status >= 500 && resp.status <= 599)\n || resp.status == 400\n || resp.status == 401\n || resp.status == 403\n || resp.status == 404) {\n return (synth(resp.status));\n }\n}\n\nsub vcl_synth {\n # Remove identifying information\n unset resp.http.Server;\n unset resp.http.X-Powered-By;\n unset resp.http.X-Varnish;\n unset resp.http.Via;\n\n # Add Content-Security-Policy\n # set resp.http.Content-Security-Policy = \"default-src 'self' *.example.ca; style-src 'self' 'unsafe-inline' *.example.ca; script-src 'self' 'unsafe-inline' 'unsafe-eval' *.example.ca *.adobedtm.com use.fontawesome.com blob:; connect-src 'self' *.example.ca *.omtrdc.net *.demdex.net *.everesttech.net; img-src 'self' *.example.ca data:;\";\n # set resp.http.X-Content-Type-Options = \"nosniff\";\n # set resp.http.X-Frame-Options = \"DENY\";\n # set resp.http.X-XSS-Protection = \"1; mode=block\";\n\n # if (resp.status >= 500 && resp.status <= 599) {\n # set resp.http.Content-Type = \"text/html; charset=utf-8\";\n # synthetic(std.fileread(\"/data/configuration/varnish/errors/503.html\"));\n # return (deliver);\n # } elseif (resp.status == 400) { # 400 - Bad Request\n # set resp.http.Content-Type = \"text/html; charset=utf-8\";\n # synthetic(std.fileread(\"/data/configuration/varnish/errors/400.html\"));\n # return (deliver);\n # } elseif (resp.status == 401) { # 401 - Unauthorized\n # set resp.http.Content-Type = \"text/html; charset=utf-8\";\n # synthetic(std.fileread(\"/data/configuration/varnish/errors/401.html\"));\n # return (deliver);\n # } elseif (resp.status == 403) { # 403 - Forbidden\n # set resp.http.Content-Type = \"text/html; charset=utf-8\";\n # synthetic(std.fileread(\"/data/configuration/varnish/errors/403.html\"));\n # return (deliver);\n # } elseif (resp.status == 404) { # 404 - Not Found\n # set resp.http.Content-Type = \"text/html; charset=utf-8\";\n # synthetic(std.fileread(\"/data/configuration/varnish/errors/404.html\"));\n # return (deliver);\n # } else\n if (resp.status == 700) { # Respond to healthcheck\n set resp.status = 200;\n set resp.http.Content-Type = \"text/plain\";\n synthetic ( {\"OK\"} );\n return (deliver);\n }\n}\n\n##\n# ERROR HANDLING\n##\n# sub vcl_backend_error {\n# set beresp.http.Content-Type = \"text/html; charset=utf-8\";\n# synthetic(std.fileread(\"/data/configuration/varnish/errors/503.html\"));\n# return (deliver);\n# }\n"` | | +| varnish.varnishConfigContent | string | `"vcl 4.0;\n\nimport std;\nimport directors;\n\nbackend nginx {\n .host = \"{{ include \"backend.fullname\" . }}-nginx\";\n .host_header = \"{{ include \"backend.fullname\" . }}-nginx\";\n .port = \"8080\";\n}\n\nsub vcl_init {\n new backends = directors.round_robin();\n backends.add_backend(nginx);\n}\n\nsub vcl_recv {\n set req.http.X-Forwarded-Host = req.http.Host;\n if (!req.http.X-Forwarded-Proto) {\n set req.http.X-Forwarded-Proto = \"http\";\n }\n\n # Answer healthcheck\n if (req.url == \"/_healthcheck\" || req.url == \"/healthcheck.txt\") {\n return (synth(700, \"HEALTHCHECK\"));\n }\n\n # Answer splashpage\n # if (req.url == \"/\") {\n # return (synth(701, \"SPLASH\"));\n # }\n\n set req.backend_hint = backends.backend();\n\n # Always cache certain file types\n # Remove cookies that Drupal doesn't care about\n if (req.url ~ \"(?i)\\.(asc|dat|tgz|png|gif|jpeg|jpg|ico|swf|css|js)(\\?.*)?$\") {\n unset req.http.Cookie;\n } else if (req.http.Cookie) {\n set req.http.Cookie = \";\" + req.http.Cookie;\n set req.http.Cookie = regsuball(req.http.Cookie, \"; +\", \";\");\n set req.http.Cookie = regsuball(req.http.Cookie, \";(SESS[a-z0-9]+|SSESS[a-z0-9]+|NO_CACHE)=\", \"; \\1=\");\n set req.http.Cookie = regsuball(req.http.Cookie, \";[^ ][^;]*\", \"\");\n set req.http.Cookie = regsuball(req.http.Cookie, \"^[; ]+|[; ]+$\", \"\");\n if (req.http.Cookie == \"\") {\n unset req.http.Cookie;\n } else {\n return (pass);\n }\n }\n # If POST, PUT or DELETE, then don't cache\n if (req.method == \"POST\" || req.method == \"PUT\" || req.method == \"DELETE\") {\n return (pass);\n }\n # Happens before we check if we have this in cache already.\n #\n # Typically you clean up the request here, removing cookies you don't need,\n # rewriting the request, etc.\n return (hash);\n #return (pass);\n}\n\nsub vcl_backend_fetch {\n # NEW\n set bereq.http.Host = \"{{ include \"backend.fullname\" . }}-nginx\";\n\n # Don't add 127.0.0.1 to X-Forwarded-For\n set bereq.http.X-Forwarded-For = regsub(bereq.http.X-Forwarded-For, \"(, )?127\\.0\\.0\\.\\d$\", \"\");\n}\n\nsub vcl_backend_response {\n if (beresp.http.Location && beresp.http.Location !~ \"^https://api.twitter.com/\") {\n set beresp.http.Location = regsub(\n beresp.http.Location,\n \"^https?://[^/]+/\",\n bereq.http.X-Forwarded-Proto + \"://\" + bereq.http.X-Forwarded-Host + \"/\"\n );\n }\n # Only cache select response codes\n if (beresp.status == 200 || beresp.status == 203 || beresp.status == 204 || beresp.status == 206 || beresp.status == 300 || beresp.status == 301 || beresp.status == 404 || beresp.status == 405 || beresp.status == 410 || beresp.status == 414 || beresp.status == 501) {\n # Cache for 5 minutes\n set beresp.ttl = 5m;\n set beresp.grace = 12h;\n set beresp.keep = 24h;\n } else {\n set beresp.ttl = 0s;\n }\n}\n\nsub vcl_deliver {\n # Remove identifying information\n unset resp.http.Server;\n unset resp.http.X-Powered-By;\n unset resp.http.X-Varnish;\n unset resp.http.Via;\n\n # Comment these for easier Drupal cache tag debugging in development.\n unset resp.http.Cache-Tags;\n unset resp.http.X-Drupal-Cache-Contexts;\n\n # Add Content-Security-Policy\n # set resp.http.Content-Security-Policy = \"default-src 'self' *.example.ca *.example.ca; style-src 'self' 'unsafe-inline' *.example.ca https://fonts.googleapis.com; script-src 'self' 'unsafe-inline' 'unsafe-eval' *.example.ca *.adobedtm.com use.fontawesome.com blob:; connect-src 'self' *.example.ca *.omtrdc.net *.demdex.net *.everesttech.net; img-src 'self' *.example.ca *.omtrdc.net *.demdex.net *.everesttech.net data:; font-src 'self' *.example.ca https://fonts.gstatic.com\";\n\n # Add CORS Headers\n # if (req.http.Origin ~ \"(?i)\\.example\\.ca$\") {\n # if (req.url ~ \"\\.(ttd|woff|woff2)(\\?.*)?$\") {\n # set resp.http.Access-Control-Allow-Origin = \"*\";\n # set resp.http.Access-Control-Allow-Methods = \"GET\";\n # }\n # }\n\n # Add X-Frame-Options\n # if (req.url ~ \"^/(en/|fr/)?media/\") {\n # set resp.http.X-Frame-Options = \"SAMEORIGIN\";\n # } else {\n # set resp.http.X-Frame-Options = \"DENY\";\n # }\n\n set resp.http.X-Content-Type-Options = \"nosniff\";\n set resp.http.X-XSS-Protection = \"1; mode=block\";\n set resp.http.Strict-Transport-Security = \"max-age=2629800\";\n\n if (req.http.host ~ \"site.example.ca\") {\n set resp.http.X-Robots-Tag = \"noindex, nofollow\";\n }\n\n if (req.url ~ \"^/(en/|fr/)?(search/|recherche/)site/\") {\n set resp.http.X-Robots-Tag = \"noindex, nofollow\";\n }\n\n # Happens when we have all the pieces we need, and are about to send the\n # response to the client.\n #\n # You can do accounting or modifying the final object here.\n if (obj.hits > 0) {\n set resp.http.X-Cache = \"HIT\";\n } else {\n set resp.http.X-Cache = \"MISS\";\n }\n # Handle errors\n if ( (resp.status >= 500 && resp.status <= 599)\n || resp.status == 400\n || resp.status == 401\n || resp.status == 403\n || resp.status == 404) {\n return (synth(resp.status));\n }\n}\n\nsub vcl_synth {\n # Remove identifying information\n unset resp.http.Server;\n unset resp.http.X-Powered-By;\n unset resp.http.X-Varnish;\n unset resp.http.Via;\n\n # Add Content-Security-Policy\n # set resp.http.Content-Security-Policy = \"default-src 'self' *.example.ca; style-src 'self' 'unsafe-inline' *.example.ca; script-src 'self' 'unsafe-inline' 'unsafe-eval' *.example.ca *.adobedtm.com use.fontawesome.com blob:; connect-src 'self' *.example.ca *.omtrdc.net *.demdex.net *.everesttech.net; img-src 'self' *.example.ca data:;\";\n # set resp.http.X-Content-Type-Options = \"nosniff\";\n # set resp.http.X-Frame-Options = \"DENY\";\n # set resp.http.X-XSS-Protection = \"1; mode=block\";\n\n set resp.http.Strict-Transport-Security = \"max-age=2629800\";\n\n # if (resp.status >= 500 && resp.status <= 599) {\n # set resp.http.Content-Type = \"text/html; charset=utf-8\";\n # synthetic(std.fileread(\"/data/configuration/varnish/errors/503.html\"));\n # return (deliver);\n # } elseif (resp.status == 400) { # 400 - Bad Request\n # set resp.http.Content-Type = \"text/html; charset=utf-8\";\n # synthetic(std.fileread(\"/data/configuration/varnish/errors/400.html\"));\n # return (deliver);\n # } elseif (resp.status == 401) { # 401 - Unauthorized\n # set resp.http.Content-Type = \"text/html; charset=utf-8\";\n # synthetic(std.fileread(\"/data/configuration/varnish/errors/401.html\"));\n # return (deliver);\n # } elseif (resp.status == 403) { # 403 - Forbidden\n # set resp.http.Content-Type = \"text/html; charset=utf-8\";\n # synthetic(std.fileread(\"/data/configuration/varnish/errors/403.html\"));\n # return (deliver);\n # } elseif (resp.status == 404) { # 404 - Not Found\n # set resp.http.Content-Type = \"text/html; charset=utf-8\";\n # synthetic(std.fileread(\"/data/configuration/varnish/errors/404.html\"));\n # return (deliver);\n # } else\n if (resp.status == 700) { # Respond to healthcheck\n set resp.status = 200;\n set resp.http.Content-Type = \"text/plain\";\n synthetic ( {\"OK\"} );\n return (deliver);\n }\n # elseif (resp.status == 701) { # Respond to splash\n # set resp.status = 200;\n # set resp.http.Content-Type = \"text/html\";\n # synthetic(std.fileread(\"/splash/index.html\"));\n # return (deliver);\n # }\n}\n\n##\n# ERROR HANDLING\n##\n# sub vcl_backend_error {\n# set beresp.http.Content-Type = \"text/html; charset=utf-8\";\n# synthetic(std.fileread(\"/data/configuration/varnish/errors/503.html\"));\n# return (deliver);\n# }\n"` | | | varnish.varnishd.image | string | `"varnish"` | | | varnish.varnishd.imagePullPolicy | string | `"IfNotPresent"` | | | varnish.varnishd.tag | string | `"6.5.1"` | | @@ -292,4 +300,4 @@ helm install --name drupal -f values-override.yaml ---------------------------------------------- -Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) +Autogenerated from chart metadata using [helm-docs v1.11.3](https://github.com/norwoodj/helm-docs/releases/v1.11.3) diff --git a/drupal/README.md.gotmpl b/charts/drupal/README.md.gotmpl similarity index 97% rename from drupal/README.md.gotmpl rename to charts/drupal/README.md.gotmpl index 5e263b39..a48e439f 100644 --- a/drupal/README.md.gotmpl +++ b/charts/drupal/README.md.gotmpl @@ -16,8 +16,8 @@ ## Prerequisites -- Kubernetes 1.7+ -- Helm v3.0.0+ +- Kubernetes 1.21+ +- Helm v3.10.0+ ## Installing the Chart @@ -36,8 +36,7 @@ Optionally you can git clone the helm chart and select the appropriate values fi ```sh git clone https://github.com/drupalwxt/helm-drupal cd helm-drupal/drupal -cp values-azurefile.yaml values-override.yaml -helm install --name drupal -f values-override.yaml +helm install --name drupal -f values-.yaml ``` ## Ingress @@ -140,7 +139,6 @@ helm install --name drupal -f values-override.yaml {{- end }} {{- end }} - ## Redis | Key | Type | Default | Description | diff --git a/drupal/charts/.gitkeep b/charts/drupal/charts/.gitkeep similarity index 100% rename from drupal/charts/.gitkeep rename to charts/drupal/charts/.gitkeep diff --git a/drupal/charts/mysql-9.1.7.tgz b/charts/drupal/charts/mysql-9.1.7.tgz similarity index 100% rename from drupal/charts/mysql-9.1.7.tgz rename to charts/drupal/charts/mysql-9.1.7.tgz diff --git a/drupal/charts/postgresql-11.6.6.tgz b/charts/drupal/charts/postgresql-11.6.6.tgz similarity index 100% rename from drupal/charts/postgresql-11.6.6.tgz rename to charts/drupal/charts/postgresql-11.6.6.tgz diff --git a/drupal/charts/redis-16.13.2.tgz b/charts/drupal/charts/redis-16.13.2.tgz similarity index 100% rename from drupal/charts/redis-16.13.2.tgz rename to charts/drupal/charts/redis-16.13.2.tgz diff --git a/charts/drupal/charts/solr-7.5.1.tgz b/charts/drupal/charts/solr-7.5.1.tgz new file mode 100644 index 0000000000000000000000000000000000000000..dd0f8e13d17b4696d504deeb61db736a8707e9f7 GIT binary patch literal 81748 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�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 'databasename', + * 'username' => 'sqlusername', + * 'password' => 'sqlpassword', + * 'host' => 'localhost', + * 'port' => '3306', + * 'driver' => 'mysql', + * 'prefix' => '', + * 'collation' => 'utf8mb4_general_ci', + * ]; + * @endcode + */ +{{- if .Values.external.enabled }} +$databases['default']['default'] = [ + 'database' => {{ .Values.external.database | quote }}, + 'username' => {{ .Values.external.user | quote }}, + 'password' => getenv('EXTERNAL_PASSWORD') ?: '', + {{- if .Values.proxysql.enabled }} + 'host' => '127.0.0.1', + {{- else if .Values.postgresql.enabled }} + 'host' => 'localhost', + {{- else }} + 'host' => {{ .Values.external.host | quote }}, + {{- end }} + 'port' => {{ .Values.external.port }}, + 'prefix' => '', + 'namespace' => 'Drupal\Core\Database\Driver\{{ .Values.external.driver }}', + 'driver' => '{{ .Values.external.driver }}', + 'collation' => 'utf8mb4_general_ci', + {{- if .Values.external.initCommands }} + 'init_commands' => [ + {{- range .Values.external.initCommands }} + {{- range $key, $value := . }} + '{{ $key }}' => {{ $value | quote }}, + {{- end }} + {{- end }} + ], + {{- end }} + {{- if .Values.external.pdo }} + 'pdo' => [ + {{- range .Values.external.pdo }} + {{- range $key, $value := . }} + {{ $key }} => {{ $value | quote }}, + {{- end }} + {{- end }} + ], + {{- end }} +]; +{{- else if .Values.mysql.enabled }} +$databases['default']['default'] = [ + 'database' => {{ .Values.mysql.auth.database | quote }}, + 'username' => {{ .Values.mysql.auth.username | quote }}, + 'password' => getenv('MYSQL_PASSWORD') ?: '', + {{- if .Values.proxysql.enabled }} + 'host' => '127.0.0.1', + {{- else }} + 'host' => '{{ .Release.Name }}-mysql', + {{- end }} + 'port' => {{ .Values.mysql.primary.service.ports.mysql | quote }}, + 'prefix' => '', + 'namespace' => 'Drupal\Core\Database\Driver\mysql', + 'driver' => 'mysql', + 'collation' => 'utf8mb4_general_ci', +]; +{{- else if .Values.postgresql.enabled }} +$databases['default']['default'] = [ + 'database' => {{ .Values.postgresql.auth.database | quote }}, + 'username' => {{ .Values.postgresql.auth.username | quote }}, + 'password' => getenv('POSTGRES_PASSWORD') ?: '', + {{- if .Values.pgbouncer.enabled }} + 'host' => 'localhost', + {{- else }} + 'host' => '{{ .Release.Name }}-postgresql', + {{- end }} + 'port' => {{ .Values.postgresql.primary.service.ports.postgresql | quote }}, + 'prefix' => '', + 'namespace' => 'Drupal\Core\Database\Driver\pgsql', + 'driver' => 'pgsql', + 'collation' => 'utf8mb4_general_ci', +]; +{{- end }} + +/** + * Customizing database settings. + * + * Many of the values of the $databases array can be customized for your + * particular database system. Refer to the sample in the section above as a + * starting point. + * + * The "driver" property indicates what Drupal database driver the + * connection should use. This is usually the same as the name of the + * database type, such as mysql or sqlite, but not always. The other + * properties will vary depending on the driver. For SQLite, you must + * specify a database file name in a directory that is writable by the + * webserver. For most other drivers, you must specify a + * username, password, host, and database name. + * + * Drupal core implements drivers for mysql, pgsql, and sqlite. Other drivers + * can be provided by contributed or custom modules. To use a contributed or + * custom driver, the "namespace" property must be set to the namespace of the + * driver. The code in this namespace must be autoloadable prior to connecting + * to the database, and therefore, prior to when module root namespaces are + * added to the autoloader. To add the driver's namespace to the autoloader, + * set the "autoload" property to the PSR-4 base directory of the driver's + * namespace. This is optional for projects managed with Composer if the + * driver's namespace is in Composer's autoloader. + * + * For each database, you may optionally specify multiple "target" databases. + * A target database allows Drupal to try to send certain queries to a + * different database if it can but fall back to the default connection if not. + * That is useful for primary/replica replication, as Drupal may try to connect + * to a replica server when appropriate and if one is not available will simply + * fall back to the single primary server (The terms primary/replica are + * traditionally referred to as master/slave in database server documentation). + * + * The general format for the $databases array is as follows: + * @code + * $databases['default']['default'] = $info_array; + * $databases['default']['replica'][] = $info_array; + * $databases['default']['replica'][] = $info_array; + * $databases['extra']['default'] = $info_array; + * @endcode + * + * In the above example, $info_array is an array of settings described above. + * The first line sets a "default" database that has one primary database + * (the second level default). The second and third lines create an array + * of potential replica databases. Drupal will select one at random for a given + * request as needed. The fourth line creates a new database with a name of + * "extra". + * + * For MySQL, MariaDB or equivalent databases the 'isolation_level' option can + * be set. The recommended transaction isolation level for Drupal sites is + * 'READ COMMITTED'. The 'REPEATABLE READ' option is supported but can result + * in deadlocks, the other two options are 'READ UNCOMMITTED' and 'SERIALIZABLE'. + * They are available but not supported; use them at your own risk. For more + * info: + * https://dev.mysql.com/doc/refman/5.7/en/innodb-transaction-isolation-levels.html + * + * On your settings.php, change the isolation level: + * @code + * $databases['default']['default']['init_commands'] = [ + * 'isolation_level' => 'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED', + * ]; + * @endcode + * + * You can optionally set a prefix for all database table names by using the + * 'prefix' setting. If a prefix is specified, the table name will be prepended + * with its value. Be sure to use valid database characters only, usually + * alphanumeric and underscore. If no prefix is desired, do not set the 'prefix' + * key or set its value to an empty string ''. + * + * For example, to have all database table prefixed with 'main_', set: + * @code + * 'prefix' => 'main_', + * @endcode + * + * Advanced users can add or override initial commands to execute when + * connecting to the database server, as well as PDO connection settings. For + * example, to enable MySQL SELECT queries to exceed the max_join_size system + * variable, and to reduce the database connection timeout to 5 seconds: + * @code + * $databases['default']['default'] = [ + * 'init_commands' => [ + * 'big_selects' => 'SET SQL_BIG_SELECTS=1', + * ], + * 'pdo' => [ + * PDO::ATTR_TIMEOUT => 5, + * ], + * ]; + * @endcode + * + * WARNING: The above defaults are designed for database portability. Changing + * them may cause unexpected behavior, including potential data loss. See + * https://www.drupal.org/developing/api/database/configuration for more + * information on these defaults and the potential issues. + * + * More details can be found in the constructor methods for each driver: + * - \Drupal\mysql\Driver\Database\mysql\Connection::__construct() + * - \Drupal\pgsql\Driver\Database\pgsql\Connection::__construct() + * - \Drupal\sqlite\Driver\Database\sqlite\Connection::__construct() + * + * Sample Database configuration format for PostgreSQL (pgsql): + * @code + * $databases['default']['default'] = [ + * 'driver' => 'pgsql', + * 'database' => 'databasename', + * 'username' => 'sqlusername', + * 'password' => 'sqlpassword', + * 'host' => 'localhost', + * 'prefix' => '', + * ]; + * @endcode + * + * Sample Database configuration format for SQLite (sqlite): + * @code + * $databases['default']['default'] = [ + * 'driver' => 'sqlite', + * 'database' => '/path/to/databasefilename', + * ]; + * @endcode + * + * Sample Database configuration format for a driver in a contributed module: + * @code + * $databases['default']['default'] = [ + * 'driver' => 'my_driver', + * 'namespace' => 'Drupal\my_module\Driver\Database\my_driver', + * 'autoload' => 'modules/my_module/src/Driver/Database/my_driver/', + * 'database' => 'databasename', + * 'username' => 'sqlusername', + * 'password' => 'sqlpassword', + * 'host' => 'localhost', + * 'prefix' => '', + * ]; + * @endcode + */ + +/** + * Location of the site configuration files. + * + * The $settings['config_sync_directory'] specifies the location of file system + * directory used for syncing configuration data. On install, the directory is + * created. This is used for configuration imports. + * + * The default location for this directory is inside a randomly-named + * directory in the public files path. The setting below allows you to set + * its location. + */ +# $settings['config_sync_directory'] = '/directory/outside/webroot'; + +/** + * Settings: + * + * $settings contains environment-specific configuration, such as the files + * directory and reverse proxy address, and temporary configuration, such as + * security overrides. + * + * @see \Drupal\Core\Site\Settings::get() + */ + +/** + * Salt for one-time login links, cancel links, form tokens, etc. + * + * This variable will be set to a random value by the installer. All one-time + * login links will be invalidated if the value is changed. Note that if your + * site is deployed on a cluster of web servers, you must ensure that this + * variable has the same value on each server. + * + * For enhanced security, you may set this variable to the contents of a file + * outside your document root, and vary the value across environments (like + * production and development); you should also ensure that this file is not + * stored with backups of your database. + * + * Example: + * @code + * $settings['hash_salt'] = file_get_contents('/home/example/salt.txt'); + * @endcode + */ +$settings['hash_salt'] = 'default'; + +/** + * Deployment identifier. + * + * Drupal's dependency injection container will be automatically invalidated and + * rebuilt when the Drupal core version changes. When updating contributed or + * custom code that changes the container, changing this identifier will also + * allow the container to be invalidated as soon as code is deployed. + */ +# $settings['deployment_identifier'] = \Drupal::VERSION; + +/** + * Access control for update.php script. + * + * If you are updating your Drupal installation using the update.php script but + * are not logged in using either an account with the "Administer software + * updates" permission or the site maintenance account (the account that was + * created during installation), you will need to modify the access check + * statement below. Change the FALSE to a TRUE to disable the access check. + * After finishing the upgrade, be sure to open this file again and change the + * TRUE back to a FALSE! + */ +$settings['update_free_access'] = FALSE; + +/** + * Fallback to HTTP for Update Manager and for fetching security advisories. + * + * If your site fails to connect to updates.drupal.org over HTTPS (either when + * fetching data on available updates, or when fetching the feed of critical + * security announcements), you may uncomment this setting and set it to TRUE to + * allow an insecure fallback to HTTP. Note that doing so will open your site up + * to a potential man-in-the-middle attack. You should instead attempt to + * resolve the issues before enabling this option. + * @see https://www.drupal.org/docs/system-requirements/php-requirements#openssl + * @see https://en.wikipedia.org/wiki/Man-in-the-middle_attack + * @see \Drupal\update\UpdateFetcher + * @see \Drupal\system\SecurityAdvisories\SecurityAdvisoriesFetcher + */ +# $settings['update_fetch_with_http_fallback'] = TRUE; + +/** + * External access proxy settings: + * + * If your site must access the Internet via a web proxy then you can enter the + * proxy settings here. Set the full URL of the proxy, including the port, in + * variables: + * - $settings['http_client_config']['proxy']['http']: The proxy URL for HTTP + * requests. + * - $settings['http_client_config']['proxy']['https']: The proxy URL for HTTPS + * requests. + * You can pass in the user name and password for basic authentication in the + * URLs in these settings. + * + * You can also define an array of host names that can be accessed directly, + * bypassing the proxy, in $settings['http_client_config']['proxy']['no']. + */ +# $settings['http_client_config']['proxy']['http'] = 'http://proxy_user:proxy_pass@example.com:8080'; +# $settings['http_client_config']['proxy']['https'] = 'http://proxy_user:proxy_pass@example.com:8080'; +# $settings['http_client_config']['proxy']['no'] = ['127.0.0.1', 'localhost']; + +/** + * Reverse Proxy Configuration: + * + * Reverse proxy servers are often used to enhance the performance + * of heavily visited sites and may also provide other site caching, + * security, or encryption benefits. In an environment where Drupal + * is behind a reverse proxy, the real IP address of the client should + * be determined such that the correct client IP address is available + * to Drupal's logging, statistics, and access management systems. In + * the most simple scenario, the proxy server will add an + * X-Forwarded-For header to the request that contains the client IP + * address. However, HTTP headers are vulnerable to spoofing, where a + * malicious client could bypass restrictions by setting the + * X-Forwarded-For header directly. Therefore, Drupal's proxy + * configuration requires the IP addresses of all remote proxies to be + * specified in $settings['reverse_proxy_addresses'] to work correctly. + * + * Enable this setting to get Drupal to determine the client IP from the + * X-Forwarded-For header. If you are unsure about this setting, do not have a + * reverse proxy, or Drupal operates in a shared hosting environment, this + * setting should remain commented out. + * + * In order for this setting to be used you must specify every possible + * reverse proxy IP address in $settings['reverse_proxy_addresses']. + * If a complete list of reverse proxies is not available in your + * environment (for example, if you use a CDN) you may set the + * $_SERVER['REMOTE_ADDR'] variable directly in settings.php. + * Be aware, however, that it is likely that this would allow IP + * address spoofing unless more advanced precautions are taken. + */ +$settings['reverse_proxy'] = TRUE; + +/** + * Reverse proxy addresses. + * + * Specify every reverse proxy IP address in your environment, as an array of + * IPv4/IPv6 addresses or subnets in CIDR notation. This setting is required if + * $settings['reverse_proxy'] is TRUE. + */ +$settings['reverse_proxy_addresses'] = ['0.0.0.0/0']; + +/** + * Reverse proxy trusted headers. + * + * Sets which headers to trust from your reverse proxy. + * + * Common values are: + * - \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_FOR + * - \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_HOST + * - \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_PORT + * - \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_PROTO + * - \Symfony\Component\HttpFoundation\Request::HEADER_FORWARDED + * + * Note the default value of + * @code + * \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_FOR | \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_HOST | \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_PORT | \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_PROTO | \Symfony\Component\HttpFoundation\Request::HEADER_FORWARDED + * @endcode + * is not secure by default. The value should be set to only the specific + * headers the reverse proxy uses. For example: + * @code + * \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_FOR | \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_HOST | \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_PORT | \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_PROTO + * @endcode + * This would trust the following headers: + * - X_FORWARDED_FOR + * - X_FORWARDED_HOST + * - X_FORWARDED_PROTO + * - X_FORWARDED_PORT + * + * @see \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_FOR + * @see \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_HOST + * @see \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_PORT + * @see \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_PROTO + * @see \Symfony\Component\HttpFoundation\Request::HEADER_FORWARDED + * @see \Symfony\Component\HttpFoundation\Request::setTrustedProxies + */ +# $settings['reverse_proxy_trusted_headers'] = \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_FOR | \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_HOST | \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_PORT | \Symfony\Component\HttpFoundation\Request::HEADER_X_FORWARDED_PROTO | \Symfony\Component\HttpFoundation\Request::HEADER_FORWARDED; + + +/** + * Page caching: + * + * By default, Drupal sends a "Vary: Cookie" HTTP header for anonymous page + * views. This tells a HTTP proxy that it may return a page from its local + * cache without contacting the web server, if the user sends the same Cookie + * header as the user who originally requested the cached page. Without "Vary: + * Cookie", authenticated users would also be served the anonymous page from + * the cache. If the site has mostly anonymous users except a few known + * editors/administrators, the Vary header can be omitted. This allows for + * better caching in HTTP proxies (including reverse proxies), i.e. even if + * clients send different cookies, they still get content served from the cache. + * However, authenticated users should access the site directly (i.e. not use an + * HTTP proxy, and bypass the reverse proxy if one is used) in order to avoid + * getting cached pages from the proxy. + */ +# $settings['omit_vary_cookie'] = TRUE; + + +/** + * Cache TTL for client error (4xx) responses. + * + * Items cached per-URL tend to result in a large number of cache items, and + * this can be problematic on 404 pages which by their nature are unbounded. A + * fixed TTL can be set for these items, defaulting to one hour, so that cache + * backends which do not support LRU can purge older entries. To disable caching + * of client error responses set the value to 0. Currently applies only to + * page_cache module. + */ +# $settings['cache_ttl_4xx'] = 3600; + +/** + * Expiration of cached forms. + * + * Drupal's Form API stores details of forms in a cache and these entries are + * kept for at least 6 hours by default. Expired entries are cleared by cron. + * + * @see \Drupal\Core\Form\FormCache::setCache() + */ +# $settings['form_cache_expiration'] = 21600; + +/** + * Class Loader. + * + * If the APCu extension is detected, the classloader will be optimized to use + * it. Set to FALSE to disable this. + * + * @see https://getcomposer.org/doc/articles/autoloader-optimization.md + */ +# $settings['class_loader_auto_detect'] = FALSE; + +/** + * Authorized file system operations: + * + * The Update Manager module included with Drupal provides a mechanism for + * site administrators to securely install missing updates for the site + * directly through the web user interface. On securely-configured servers, + * the Update manager will require the administrator to provide SSH or FTP + * credentials before allowing the installation to proceed; this allows the + * site to update the new files as the user who owns all the Drupal files, + * instead of as the user the webserver is running as. On servers where the + * webserver user is itself the owner of the Drupal files, the administrator + * will not be prompted for SSH or FTP credentials (note that these server + * setups are common on shared hosting, but are inherently insecure). + * + * Some sites might wish to disable the above functionality, and only update + * the code directly via SSH or FTP themselves. This setting completely + * disables all functionality related to these authorized file operations. + * + * @see https://www.drupal.org/node/244924 + * + * Remove the leading hash signs to disable. + */ +# $settings['allow_authorize_operations'] = FALSE; + +/** + * Default mode for directories and files written by Drupal. + * + * Value should be in PHP Octal Notation, with leading zero. + */ +# $settings['file_chmod_directory'] = 0775; +# $settings['file_chmod_file'] = 0664; + +/** + * Optimized assets path: + * + * A local file system path where optimized assets will be stored. This directory + * must exist and be writable by Drupal. This directory must be relative to + * the Drupal installation directory and be accessible over the web. + */ +# $settings['file_assets_path'] = 'sites/default/files'; + +/** + * Public file base URL: + * + * An alternative base URL to be used for serving public files. This must + * include any leading directory path. + * + * A different value from the domain used by Drupal to be used for accessing + * public files. This can be used for a simple CDN integration, or to improve + * security by serving user-uploaded files from a different domain or subdomain + * pointing to the same server. Do not include a trailing slash. + */ +# $settings['file_public_base_url'] = 'http://downloads.example.com/files'; + +/** + * Public file path: + * + * A local file system path where public files will be stored. This directory + * must exist and be writable by Drupal. This directory must be relative to + * the Drupal installation directory and be accessible over the web. + */ +# $settings['file_public_path'] = 'sites/default/files'; + +/** + * Additional public file schemes: + * + * Public schemes are URI schemes that allow download access to all users for + * all files within that scheme. + * + * The "public" scheme is always public, and the "private" scheme is always + * private, but other schemes, such as "https", "s3", "example", or others, + * can be either public or private depending on the site. By default, they're + * private, and access to individual files is controlled via + * hook_file_download(). + * + * Typically, if a scheme should be public, a module makes it public by + * implementing hook_file_download(), and granting access to all users for all + * files. This could be either the same module that provides the stream wrapper + * for the scheme, or a different module that decides to make the scheme + * public. However, in cases where a site needs to make a scheme public, but + * is unable to add code in a module to do so, the scheme may be added to this + * variable, the result of which is that system_file_download() grants public + * access to all files within that scheme. + */ +# $settings['file_additional_public_schemes'] = ['example']; + +/** + * File schemes whose paths should not be normalized: + * + * Normally, Drupal normalizes '/./' and '/../' segments in file URIs in order + * to prevent unintended file access. For example, 'private://css/../image.png' + * is normalized to 'private://image.png' before checking access to the file. + * + * On Windows, Drupal also replaces '\' with '/' in URIs for the local + * filesystem. + * + * If file URIs with one or more scheme should not be normalized like this, then + * list the schemes here. For example, if 'porcelain://china/./plate.png' should + * not be normalized to 'porcelain://china/plate.png', then add 'porcelain' to + * this array. In this case, make sure that the module providing the 'porcelain' + * scheme does not allow unintended file access when using '/../' to move up the + * directory tree. + */ +# $settings['file_sa_core_2023_005_schemes'] = ['porcelain']; + +/** + * Configuration for phpinfo() admin status report. + * + * Drupal's admin UI includes a report at admin/reports/status/php which shows + * the output of phpinfo(). The full output can contain sensitive information + * so by default Drupal removes some sections. + * + * This behaviour can be configured by setting this variable to a different + * value corresponding to the flags parameter of phpinfo(). + * + * If you need to expose more information in the report - for example to debug a + * problem - consider doing so temporarily. + * + * @see https://www.php.net/manual/function.phpinfo.php + */ +# $settings['sa_core_2023_004_phpinfo_flags'] = ~ (INFO_VARIABLES | INFO_ENVIRONMENT); + +/** + * Private file path: + * + * A local file system path where private files will be stored. This directory + * must be absolute, outside of the Drupal installation directory and not + * accessible over the web. + * + * Note: Caches need to be cleared when this value is changed to make the + * private:// stream wrapper available to the system. + * + * See https://www.drupal.org/documentation/modules/file for more information + * about securing private files. + */ +$settings['file_private_path'] = '/private'; + +/** + * Temporary file path: + * + * A local file system path where temporary files will be stored. This directory + * must be absolute, outside of the Drupal installation directory and not + * accessible over the web. + * + * If this is not set, the default for the operating system will be used. + * + * @see \Drupal\Component\FileSystem\FileSystem::getOsTemporaryDirectory() + */ +# $settings['file_temp_path'] = '/tmp'; + +/** + * Session write interval: + * + * Set the minimum interval between each session write to database. + * For performance reasons it defaults to 180. + */ +# $settings['session_write_interval'] = 180; + +/** + * String overrides: + * + * To override specific strings on your site with or without enabling the Locale + * module, add an entry to this list. This functionality allows you to change + * a small number of your site's default English language interface strings. + * + * Remove the leading hash signs to enable. + * + * The "en" part of the variable name, is dynamic and can be any langcode of + * any added language. (eg locale_custom_strings_de for german). + */ +# $settings['locale_custom_strings_en'][''] = [ +# 'Home' => 'Front page', +# '@count min' => '@count minutes', +# ]; + +/** + * A custom theme for the offline page: + * + * This applies when the site is explicitly set to maintenance mode through the + * administration page or when the database is inactive due to an error. + * The template file should also be copied into the theme. It is located inside + * 'core/modules/system/templates/maintenance-page.html.twig'. + * + * Note: This setting does not apply to installation and update pages. + */ +# $settings['maintenance_theme'] = 'claro'; + +/** + * PHP settings: + * + * To see what PHP settings are possible, including whether they can be set at + * runtime (by using ini_set()), read the PHP documentation: + * http://php.net/manual/ini.list.php + * See \Drupal\Core\DrupalKernel::bootEnvironment() for required runtime + * settings and the .htaccess file for non-runtime settings. + * Settings defined there should not be duplicated here so as to avoid conflict + * issues. + */ + +/** + * If you encounter a situation where users post a large amount of text, and + * the result is stripped out upon viewing but can still be edited, Drupal's + * output filter may not have sufficient memory to process it. If you + * experience this issue, you may wish to uncomment the following two lines + * and increase the limits of these variables. For more information, see + * http://php.net/manual/pcre.configuration.php. + */ +# ini_set('pcre.backtrack_limit', 200000); +# ini_set('pcre.recursion_limit', 200000); + +/** + * Configuration overrides. + * + * To globally override specific configuration values for this site, + * set them here. You usually don't need to use this feature. This is + * useful in a configuration file for a vhost or directory, rather than + * the default settings.php. + * + * Note that any values you provide in these variable overrides will not be + * viewable from the Drupal administration interface. The administration + * interface displays the values stored in configuration so that you can stage + * changes to other environments that don't have the overrides. + * + * There are particular configuration values that are risky to override. For + * example, overriding the list of installed modules in 'core.extension' is not + * supported as module install or uninstall has not occurred. Other examples + * include field storage configuration, because it has effects on database + * structure, and 'core.menu.static_menu_link_overrides' since this is cached in + * a way that is not config override aware. Also, note that changing + * configuration values in settings.php will not fire any of the configuration + * change events. + */ +# $config['system.site']['name'] = 'My Drupal site'; +# $config['user.settings']['anonymous'] = 'Visitor'; + +/** + * Load services definition file. + */ +$settings['container_yamls'][] = $app_root . '/' . $site_path . '/services.yml'; + +/** + * Override the default service container class. + * + * This is useful for example to trace the service container for performance + * tracking purposes, for testing a service container with an error condition or + * to test a service container that throws an exception. + */ +# $settings['container_base_class'] = '\Drupal\Core\DependencyInjection\Container'; + +/** + * Override the default yaml parser class. + * + * Provide a fully qualified class name here if you would like to provide an + * alternate implementation YAML parser. The class must implement the + * \Drupal\Component\Serialization\SerializationInterface interface. + */ +# $settings['yaml_parser_class'] = NULL; + +/** + * Trusted host configuration. + * + * Drupal core can use the Symfony trusted host mechanism to prevent HTTP Host + * header spoofing. + * + * To enable the trusted host mechanism, you enable your allowable hosts + * in $settings['trusted_host_patterns']. This should be an array of regular + * expression patterns, without delimiters, representing the hosts you would + * like to allow. + * + * For example: + * @code + * $settings['trusted_host_patterns'] = [ + * '^www\.example\.com$', + * ]; + * @endcode + * will allow the site to only run from www.example.com. + * + * If you are running multisite, or if you are running your site from + * different domain names (eg, you don't redirect http://www.example.com to + * http://example.com), you should specify all of the host patterns that are + * allowed by your site. + * + * For example: + * @code + * $settings['trusted_host_patterns'] = [ + * '^example\.com$', + * '^.+\.example\.com$', + * '^example\.org$', + * '^.+\.example\.org$', + * ]; + * @endcode + * will allow the site to run off of all variants of example.com and + * example.org, with all subdomains included. + * + * @see https://www.drupal.org/docs/installing-drupal/trusted-host-settings + */ +# $settings['trusted_host_patterns'] = []; + +/** + * The default list of directories that will be ignored by Drupal's file API. + * + * By default ignore node_modules and bower_components folders to avoid issues + * with common frontend tools and recursive scanning of directories looking for + * extensions. + * + * @see \Drupal\Core\File\FileSystemInterface::scanDirectory() + * @see \Drupal\Core\Extension\ExtensionDiscovery::scanDirectory() + */ +$settings['file_scan_ignore_directories'] = [ + 'node_modules', + 'bower_components', +]; + +/** + * The default number of entities to update in a batch process. + * + * This is used by update and post-update functions that need to go through and + * change all the entities on a site, so it is useful to increase this number + * if your hosting configuration (i.e. RAM allocation, CPU speed) allows for a + * larger number of entities to be processed in a single batch run. + */ +$settings['entity_update_batch_size'] = 50; + +/** + * Entity update backup. + * + * This is used to inform the entity storage handler that the backup tables as + * well as the original entity type and field storage definitions should be + * retained after a successful entity update process. + */ +$settings['entity_update_backup'] = TRUE; + +/** + * Node migration type. + * + * This is used to force the migration system to use the classic node migrations + * instead of the default complete node migrations. The migration system will + * use the classic node migration only if there are existing migrate_map tables + * for the classic node migrations and they contain data. These tables may not + * exist if you are developing custom migrations and do not want to use the + * complete node migrations. Set this to TRUE to force the use of the classic + * node migrations. + */ +$settings['migrate_node_migrate_type_classic'] = FALSE; + +/** + * The default settings for migration sources. + * + * These settings are used as the default settings on the Credential form at + * /upgrade/credentials. + * + * - migrate_source_version - The version of the source database. This can be + * '6' or '7'. Defaults to '7'. + * - migrate_source_connection - The key in the $databases array for the source + * site. + * - migrate_file_public_path - The location of the source Drupal 6 or Drupal 7 + * public files. This can be a local file directory containing the source + * Drupal 6 or Drupal 7 site (e.g /var/www/docroot), or the site address + * (e.g http://example.com). + * - migrate_file_private_path - The location of the source Drupal 7 private + * files. This can be a local file directory containing the source Drupal 7 + * site (e.g /var/www/docroot), or empty to use the same value as Public + * files directory. + * + * Sample configuration for a drupal 6 source site with the source files in a + * local directory. + * + * @code + * $settings['migrate_source_version'] = '6'; + * $settings['migrate_source_connection'] = 'migrate'; + * $settings['migrate_file_public_path'] = '/var/www/drupal6'; + * @endcode + * + * Sample configuration for a drupal 7 source site with public source files on + * the source site and the private files in a local directory. + * + * @code + * $settings['migrate_source_version'] = '7'; + * $settings['migrate_source_connection'] = 'migrate'; + * $settings['migrate_file_public_path'] = 'https://drupal7.com'; + * $settings['migrate_file_private_path'] = '/var/www/drupal7'; + * @endcode + */ +# $settings['migrate_source_connection'] = ''; +# $settings['migrate_source_version'] = ''; +# $settings['migrate_file_public_path'] = ''; +# $settings['migrate_file_private_path'] = ''; + +/** + * Load local development override configuration, if available. + * + * Create a settings.local.php file to override variables on secondary (staging, + * development, etc.) installations of this site. + * + * Typical uses of settings.local.php include: + * - Disabling caching. + * - Disabling JavaScript/CSS compression. + * - Rerouting outgoing emails. + * + * Keep this code block at the end of this file to take full effect. + */ +# +# if (file_exists($app_root . '/' . $site_path . '/settings.local.php')) { +# include $app_root . '/' . $site_path . '/settings.local.php'; +# } + +$settings["config_sync_directory"] = '{{ .Values.drupal.configSync.directory }}'; + +{{- if .Values.drupal.configSplit.enabled }} +/** + * Configuration Split for Configuration Management + * + * WxT is following the best practices given by Acquia for configuration + * management. The "default" configuration directory should be shared between + * all multi-sites, and each multisite will override this selectively using + * configuration splits. + * + * To disable this functionality simply set the following parameters: + * $wxt_override_config_dirs = FALSE; + * $settings['config_sync_directory'] = $dir . "/private/config/$site_dir"; + * + * See https://github.com/acquia/blt/blob/12.x/settings/config.settings.php + * for more information. + */ + +use Drupal\wxt\Robo\Common\EnvironmentDetector; + +if (!isset($wxt_override_config_dirs)) { + $wxt_override_config_dirs = TRUE; +} +if ($wxt_override_config_dirs) { + $config_directories['sync'] = $repo_root . "/private/config/default"; + $settings['config_sync_directory'] = $repo_root . "/private/config/default"; +} +$split_filename_prefix = 'config_split.config_split'; +if (isset($config_directories['sync'])) { + $split_filepath_prefix = $config_directories['sync'] . '/' . $split_filename_prefix; +} +else { + $split_filepath_prefix = $settings['config_sync_directory'] . '/' . $split_filename_prefix; +} + +/** + * Set environment splits. + */ +$split_envs = [ + 'local', + 'dev', + 'test', + 'qa', + 'prod', + 'ci', +]; +foreach ($split_envs as $split_env) { + $config["$split_filename_prefix.$split_env"]['status'] = FALSE; +} +if (!isset($split)) { + $split = 'none'; + if (EnvironmentDetector::isLocalEnv()) { + $split = 'local'; + } + if (EnvironmentDetector::isCiEnv()) { + $split = 'ci'; + } + if (EnvironmentDetector::isDevEnv()) { + $split = 'dev'; + } + elseif (EnvironmentDetector::isTestEnv()) { + $split = 'test'; + } + elseif (EnvironmentDetector::isQaEnv()) { + $split = 'qa'; + } + elseif (EnvironmentDetector::isProdEnv()) { + $split = 'prod'; + } +} +if ($split != 'none') { + $config["$split_filename_prefix.$split"]['status'] = TRUE; +} + +/** + * Set multisite split. + */ +// $config["$split_filename_prefix.SITENAME"]['status'] = TRUE; +{{- end }} + +{{- if .Values.redis.enabled }} +if (extension_loaded('redis')) { + // Set Redis as the default backend for any cache bin not otherwise specified. + $settings['cache']['default'] = 'cache.backend.redis'; + $settings['redis.connection']['interface'] = '{{ default "PhpRedis" .Values.redis.clientInterface }}'; + $settings['redis.connection']['scheme'] = 'http'; + {{- if .Values.redis.sentinel.enabled }} + $settings['redis.connection']['host'] = ['{{ .Release.Name }}-redis:{{ .Values.redis.sentinel.service.sentinelPort }}']; + $settings['redis.connection']['instance'] = '{{ .Values.redis.sentinel.masterSet }}'; + {{- else }} + $settings['redis.connection']['host'] = '{{ .Release.Name }}-redis-master'; + $settings['redis.connection']['port'] = '{{ .Values.redis.master.service.ports.redis }}'; + {{- end }} + $settings['redis.connection']['password'] = getenv('REDIS_PASSWORD') ?: ''; + $settings['redis.connection']['persistent'] = FALSE; + + // Allow the services to work before the Redis module itself is enabled. + $settings['container_yamls'][] = 'modules/contrib/redis/example.services.yml'; + $settings['container_yamls'][] = 'modules/contrib/redis/redis.services.yml'; + + // Manually add the classloader path, this is required for the container cache bin definition below + // and allows to use it without the redis module being enabled. + $class_loader->addPsr4('Drupal\\redis\\', 'modules/contrib/redis/src'); + + $settings['bootstrap_container_definition'] = [ + 'parameters' => [], + 'services' => [ + 'redis.factory' => [ + 'class' => 'Drupal\redis\ClientFactory', + ], + 'cache.backend.redis' => [ + 'class' => 'Drupal\redis\Cache\CacheBackendFactory', + 'arguments' => ['@redis.factory', '@cache_tags_provider.container', '@serialization.phpserialize'], + ], + 'cache.container' => [ + 'class' => '\Drupal\redis\Cache\PhpRedis', + 'factory' => ['@cache.backend.redis', 'get'], + 'arguments' => ['container'], + ], + 'cache_tags_provider.container' => [ + 'class' => 'Drupal\redis\Cache\RedisCacheTagsChecksum', + 'arguments' => ['@redis.factory'], + ], + 'serialization.phpserialize' => [ + 'class' => 'Drupal\Component\Serialization\PhpSerialize', + ], + ], + ]; + + /** Optional prefix for cache entries */ + $settings['cache_prefix'] = 'drupal_'; + + // Always set the fast backend for bootstrap, discover and config, otherwise + // this gets lost when redis is enabled. + $settings['cache']['bins']['bootstrap'] = 'cache.backend.chainedfast'; + $settings['cache']['bins']['discovery'] = 'cache.backend.chainedfast'; + $settings['cache']['bins']['config'] = 'cache.backend.chainedfast'; + + // Use for all bins otherwise specified. + $settings['cache']['default'] = 'cache.backend.redis'; + + // Use for all queues unless otherwise specified for a specific queue. + $settings['queue_default'] = 'queue.redis'; + + // Or if you want to use reliable queue implementation. + // $settings['queue_default'] = 'queue.redis_reliable'; + + // Use this to only use Redis for a specific queue. + // $settings['queue_service_aggregator_feeds'] = 'queue.redis'; + + // Use this to use reliable queue implementation. + // $settings['queue_service_aggregator_feeds'] = 'queue.redis_reliable'; +} +{{- end }} + +// As recommended in the S3FS docs, change the twig storage directory +$settings['php_storage']['twig']['directory'] = '/cache/twig'; + +if (is_file(__DIR__ . '/extra.settings.php')) { + include __DIR__ . '/extra.settings.php'; +} diff --git a/drupal/conf/settings.d9.php b/charts/drupal/conf/settings.d9.php similarity index 100% rename from drupal/conf/settings.d9.php rename to charts/drupal/conf/settings.d9.php diff --git a/drupal/conf/ssmtp.conf b/charts/drupal/conf/ssmtp.conf similarity index 100% rename from drupal/conf/ssmtp.conf rename to charts/drupal/conf/ssmtp.conf diff --git a/drupal/conf/userlist.txt b/charts/drupal/conf/userlist.txt similarity index 100% rename from drupal/conf/userlist.txt rename to charts/drupal/conf/userlist.txt diff --git a/charts/drupal/conf/www.conf b/charts/drupal/conf/www.conf new file mode 100644 index 00000000..bef0c6fa --- /dev/null +++ b/charts/drupal/conf/www.conf @@ -0,0 +1,5 @@ +[www] +user = www-data +group = www-data +listen = 127.0.0.1:9000 +pm = dynamic diff --git a/drupal/templates/NOTES.txt b/charts/drupal/templates/NOTES.txt similarity index 96% rename from drupal/templates/NOTES.txt rename to charts/drupal/templates/NOTES.txt index 8ac76223..af4f982d 100644 --- a/drupal/templates/NOTES.txt +++ b/charts/drupal/templates/NOTES.txt @@ -87,9 +87,18 @@ kubectl exec -it $POD_NAME -n {{ .Release.Namespace }} -- drush si {{ .Values.dr ** Login +{{- if .Values.drupal.usePasswordFiles }} + + echo Username: {{ .Values.drupal.username }} + echo Password: "Password is handled by Vault" + +{{- else }} + echo Username: {{ .Values.drupal.username }} echo Password: $(kubectl get secret --namespace {{ .Release.Namespace }} {{ template "drupal.fullname" . }} -o jsonpath="{.data.password}" | base64 --decode) +{{- end }} + ** Running Drush commands export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/instance={{ .Release.Name }},tier=drupal" -o jsonpath="{.items[0].metadata.name}") diff --git a/charts/drupal/templates/_helpers.tpl b/charts/drupal/templates/_helpers.tpl new file mode 100644 index 00000000..29b74d45 --- /dev/null +++ b/charts/drupal/templates/_helpers.tpl @@ -0,0 +1,325 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* +Renders a value that contains template. +Usage: +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $) }} +*/}} +{{- define "common.tplvalues.render" -}} +{{- if typeIs "string" .value }} + {{- tpl .value .context }} +{{- else }} + {{- tpl (.value | toYaml) .context }} +{{- end }} +{{- end -}} + +{{/* +Expand the name of the chart. +*/}} +{{- define "drupal.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 "drupal.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 a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "backend.fullname" -}} +{{- $name := default "drupal" .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "drupal.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "drupal.serviceAccountName" -}} +{{- if .Values.drupal.serviceAccount.create }} +{{- default (include "drupal.fullname" .) .Values.drupal.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.drupal.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create common environment variables for Drupal +*/}} +{{- define "drupal.env" -}} +{{- if .Values.external.enabled }} +- name: EXTERNAL_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "drupal.fullname" . }} + key: databasePassword +{{- else if and .Values.mysql.enabled (not .Values.mysql.auth.usePasswordFiles) }} +- name: MYSQL_PASSWORD + valueFrom: + secretKeyRef: + name: "{{ .Release.Name }}-mysql" + key: mysql-password +{{- else if .Values.postgresql.enabled }} +- name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: "{{ .Release.Name }}-postgresql" + key: password +{{- end }} +{{- if .Values.redis.enabled }} +- name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: "{{ .Release.Name }}-redis" + key: redis-password +{{- end }} +{{- if not .Values.drupal.usePasswordFiles }} +- name: DRUPAL_ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "drupal.fullname" . }} + key: password +{{- end }} +{{- end -}} + +{{/* +Create initContainers for Drupal +*/}} +{{- define "drupal.initContainers" -}} +{{- if .Values.drupal.volumePermissions.enabled }} +- name: set-volume-permissions + image: 'alpine:3.10' + command: + - chown + - '-R' + - '84:84' + - /files/public + - /files/private + volumeMounts: + - name: files-public + mountPath: /files/public + - name: files-private + mountPath: /files/private + securityContext: + runAsUser: 0 +{{- end }} +{{- if .Values.azure.sharedDisk.enabled }} +- name: init-chown + image: 'alpine:3.10' + command: + - chown + - '-R' + - '82:82' + - /mnt/azure + volumeMounts: + - name: files-public + mountPath: /mnt/azure +{{- end }} +{{- if or (and .Values.azure.azureFile.enabled .Values.azure.azureFile.initMediaIconsFolder) (and .Values.azure.sharedDisk.enabled .Values.azure.sharedDisk.initMediaIconsFolder) }} +- name: init-media-icons-folder + image: 'alpine:3.10' + command: + - mkdir + - '-p' + - /files/media-icons/generic + volumeMounts: + - name: files-public + mountPath: /files +{{- end }} +{{- if not (eq .Values.drupal.siteRoot "/") }} +- name: init-site-root + image: 'alpine:3.10' + command: + - /bin/sh + - '-c' + - | + mkdir -p "/webroot$(dirname "{{ .Values.drupal.siteRoot }}")" + ln -s /var/www/html "/webroot{{ .Values.drupal.siteRoot }}" + volumeMounts: + - name: webroot + mountPath: /webroot +{{- end }} +{{- if .Values.drupal.initContainers }} +{{- toYaml .Values.drupal.initContainers }} +{{- end }} +{{- end -}} + +{{/* +Create common volume mounts for Drupal +*/}} +{{- define "drupal.volumeMounts" -}} +- name: cm-drupal + readOnly: true + mountPath: /usr/local/etc/php/php.ini + subPath: php.ini +- name: cm-drupal + readOnly: true + mountPath: /usr/local/etc/php/conf.d/opcache-recommended.ini + subPath: opcache-recommended.ini +- name: cm-drupal + readOnly: true + mountPath: /usr/local/etc/php-fpm.d/www.conf + subPath: www.conf +- name: cm-drupal + mountPath: /var/www/html/sites/default/settings.php + subPath: settings.php + readOnly: true +- name: cm-drupal + mountPath: /var/www/html/sites/default/extra.settings.php + subPath: extra.settings.php + readOnly: true +- name: cm-drupal + mountPath: /var/www/html/sites/default/services.yml + subPath: services.yml + readOnly: true +- name: ssmtp + mountPath: /etc/ssmtp/ssmtp.conf + subPath: ssmtp.conf + readOnly: true +- name: twig-cache + mountPath: /cache/twig +{{- if not .Values.drupal.disableDefaultFilesMount }} +- name: files + mountPath: /var/www/html/sites/default/files + subPath: public +- name: files + mountPath: /private + subPath: private +{{- end }} +{{- if not (eq .Values.drupal.siteRoot "/") }} +- name: webroot + mountPath: /webroot +{{- end }} +{{- end -}} + +{{/* +Create common volumes for Drupal +*/}} +{{- define "drupal.volumes" -}} +{{- $fullName := include "drupal.fullname" . -}} +- name: cm-drupal + configMap: + name: {{ $fullName }} +- name: ssmtp + secret: + secretName: {{ $fullName }}-ssmtp + items: + - key: ssmtp.conf + path: ssmtp.conf +- name: twig-cache + emptyDir: {} +{{- if .Values.drupal.persistence.enabled }} +- name: files + persistentVolumeClaim: + claimName: {{ $fullName }}-drupal +{{- else if or (.Values.azure.azureFile.enabled) (.Values.azure.sharedDisk.enabled) }} +- name: files-public + persistentVolumeClaim: + claimName: {{ $fullName }}-public +- name: files-private + persistentVolumeClaim: + claimName: {{ $fullName }}-private +{{- else if not .Values.drupal.disableDefaultFilesMount }} +- name: files + emptyDir: {} +{{- end }} +{{- if not (eq .Values.drupal.siteRoot "/") }} +- name: webroot + emptyDir: {} +{{- end }} +{{- if .Values.drupal.volumes }} +{{ toYaml .Values.drupal.volumes }} +{{- end }} +{{- end -}} + +{{/* +Create connection pooler for Drupal +*/}} +{{- define "drupal.connectionPooler" -}} +{{- if .Values.proxysql.enabled }} +- name: proxysql + image: proxysql/proxysql:2.1.0 + imagePullPolicy: Always + ports: + - containerPort: 6032 + - containerPort: 6033 + volumeMounts: + - name: configfiles + mountPath: "/etc/proxysql" + readOnly: true + livenessProbe: + tcpSocket: + port: 6032 + periodSeconds: 60 + command: ["/usr/bin/proxysql", "--initial", "-f", "-c", "/etc/proxysql/proxysql.conf"] + securityContext: + allowPrivilegeEscalation: false + runAsUser: 0 + runAsGroup: 999 +{{- else if .Values.pgbouncer.enabled }} +- name: pgbouncer + image: mcr.microsoft.com/azure-oss-db-tools/pgbouncer-sidecar:latest + imagePullPolicy: Always + ports: + - containerPort: 5432 + volumeMounts: + - name: configfiles + mountPath: "/etc/pgbouncer" + readOnly: true + livenessProbe: + tcpSocket: + port: 5432 + periodSeconds: 60 + lifecycle: + preStop: + exec: + command: ["/bin/sh", "-c", "killall -INT pgbouncer && sleep 120"] + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: ['all'] +{{- end }} +{{- end -}} + +{{/* +Create connection pooler for Drupal +*/}} +{{- define "drupal.connectionPooler.volumes" -}} +{{- $fullName := include "drupal.fullname" . -}} +{{- if .Values.proxysql.enabled }} +- name: configfiles + secret: + secretName: {{ $fullName }}-proxysql +{{- else if .Values.pgbouncer.enabled }} +- name: configfiles + secret: + secretName: {{ $fullName }}-pgbouncer +{{- end }} +{{- end -}} diff --git a/charts/drupal/templates/cm/drupal.yaml b/charts/drupal/templates/cm/drupal.yaml new file mode 100644 index 00000000..a9b6db59 --- /dev/null +++ b/charts/drupal/templates/cm/drupal.yaml @@ -0,0 +1,40 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "drupal.fullname" . }} + labels: + app.kubernetes.io/name: {{ include "drupal.name" . }} + helm.sh/chart: {{ include "drupal.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +data: + php.ini: | + {{- tpl (.Files.Get "conf/php.ini") . | nindent 4 }} + opcache-recommended.ini: | + {{- tpl (.Files.Get "conf/opcache-recommended.ini") . | nindent 4 }} + www.conf: | + {{- tpl (.Files.Get "conf/www.conf") . | nindent 4 }} + {{- .Values.drupal.php.fpm | nindent 4}} + settings.php: | + {{- if eq "d9" .Values.drupal.version }} + {{- tpl (.Files.Get "conf/settings.d9.php") . | nindent 4 }} + {{- else if eq "d10" .Values.drupal.version }} + {{- tpl (.Files.Get "conf/settings.d10.php") . | nindent 4 }} + {{- else }} + settings.php: + =1.21" $.Capabilities.KubeVersion.GitVersion }} +apiVersion: batch/v1 +{{- else }} +apiVersion: batch/v1beta1 +{{- end }} +kind: CronJob +metadata: + name: {{ $fullName }}-{{ $cronName }} + labels: + app.kubernetes.io/name: {{ $name }} + helm.sh/chart: {{ $chartName }} + app.kubernetes.io/instance: {{ $release.Name }} + app.kubernetes.io/managed-by: {{ $release.Service }} +spec: + schedule: "{{ $cron.schedule }}" + startingDeadlineSeconds: 100 + concurrencyPolicy: Replace + successfulJobsHistoryLimit: {{ $values.drupal.cron.successfulJobsHistoryLimit }} + failedJobsHistoryLimit: {{ $values.drupal.cron.failedJobsHistoryLimit }} + jobTemplate: + spec: + template: + metadata: + labels: + app.kubernetes.io/name: {{ $name }} + helm.sh/chart: {{ $chartName }} + app.kubernetes.io/instance: {{ $release.Name }} + app.kubernetes.io/managed-by: {{ $release.Service }} + {{- if $values.drupal.podAnnotations }} + annotations: + {{- toYaml $values.drupal.podAnnotations | nindent 12 }} + {{- end }} + spec: + serviceAccountName: {{ include "drupal.serviceAccountName" $ctx }} + {{- if $values.drupal.tolerations }} + tolerations: + {{- toYaml $values.drupal.tolerations | nindent 10 }} + {{- end }} + {{- if $values.drupal.nodeSelector }} + nodeSelector: + {{- toYaml $values.drupal.nodeSelector | nindent 12 }} + {{- end }} + restartPolicy: OnFailure + containers: + - name: cron + image: "{{ $values.drupal.image }}:{{ default $chart.AppVersion $values.drupal.tag }}" + imagePullPolicy: {{ default "" $values.drupal.imagePullPolicy | quote }} + command: + - '/bin/sh' + - '-c' + - | + # Errors should fail the job + set -e + + # Pre Install scripts + {{- if $values.drupal.cron.preInstallScripts }} + {{ toYaml $values.drupal.cron.preInstallScripts | nindent 14}} + {{- end }} + +{{ $cron.script | indent 16 }} + + env: + {{- include "drupal.env" $ctx | nindent 14 }} + {{- if $values.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" $values.extraEnvVars "context" $) | nindent 14 }} + {{- end }} + volumeMounts: + {{- include "drupal.volumeMounts" $ctx | nindent 14 }} + {{- if $values.drupal.volumeMounts }} + {{- include "common.tplvalues.render" (dict "value" $values.drupal.volumeMounts "context" $) | nindent 14 }} + {{- end }} + {{- if $cron.volumeMounts }} + {{- include "common.tplvalues.render" (dict "value" $cron.volumeMounts "context" $) | nindent 14 }} + {{- end }} + {{- include "drupal.connectionPooler" $ctx | nindent 10 }} + {{- if $values.drupal.imagePullSecrets }} + imagePullSecrets: + {{- toYaml $values.drupal.imagePullSecrets | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml $values.drupal.securityContext | nindent 12 }} + volumes: + {{- include "drupal.volumes" $ctx | nindent 10 }} + {{- include "drupal.connectionPooler.volumes" $ctx | nindent 10 }} + {{- if $cron.volumes }} + {{- toYaml $cron.volumes | nindent 10 }} + {{- end }} +{{- end }} +{{- end }} diff --git a/charts/drupal/templates/cronjob/drupal-backup.yaml b/charts/drupal/templates/cronjob/drupal-backup.yaml new file mode 100644 index 00000000..31369aaf --- /dev/null +++ b/charts/drupal/templates/cronjob/drupal-backup.yaml @@ -0,0 +1,107 @@ +{{- if .Values.drupal.backup.enabled }} +{{- if semverCompare ">=1.21" $.Capabilities.KubeVersion.GitVersion }} +apiVersion: batch/v1 +{{- else }} +apiVersion: batch/v1beta1 +{{- end }} +kind: CronJob +metadata: + name: {{ template "drupal.fullname" . }}-drupal-backup + labels: + app.kubernetes.io/name: {{ include "drupal.name" . }} + helm.sh/chart: {{ include "drupal.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + schedule: "{{ .Values.drupal.backup.schedule }}" + startingDeadlineSeconds: 100 + concurrencyPolicy: Replace + successfulJobsHistoryLimit: {{ .Values.drupal.cron.successfulJobsHistoryLimit }} + failedJobsHistoryLimit: {{ .Values.drupal.cron.failedJobsHistoryLimit }} + jobTemplate: + spec: + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "drupal.name" . }} + helm.sh/chart: {{ include "drupal.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + annotations: + {{- if .Values.drupal.podAnnotations }} + {{- toYaml .Values.drupal.podAnnotations | nindent 12 }} + {{- end }} + spec: + serviceAccountName: {{ include "drupal.serviceAccountName" . }} + {{- if .Values.drupal.tolerations }} + tolerations: + {{- toYaml .Values.drupal.tolerations | nindent 12 }} + {{- end }} + {{- if .Values.drupal.nodeSelector }} + nodeSelector: + {{- toYaml .Values.drupal.nodeSelector | nindent 12 }} + {{- end }} + restartPolicy: OnFailure + containers: + - name: drush + image: "{{ .Values.drupal.image }}:{{ default .Chart.AppVersion .Values.drupal.tag }}" + imagePullPolicy: {{ default "" .Values.drupal.imagePullPolicy | quote }} + command: + - '/bin/sh' + - '-c' + - | + # Errors should fail the job + set -e + + # Pre Install scripts + {{- if .Values.drupal.cron.preInstallScripts }} + {{ .Values.drupal.cron.preInstallScripts | nindent 14}} + {{- end }} + + # Wait for DB to be available + until drush sql:query 'SHOW TABLES;'; do echo Waiting for DB; sleep 3; done + echo DB available + + # Check Drush status + drush status + + # Run cron + BACKUPNAME=$(date +%Y%m%d.%H%M%S) + mkdir -p /backup/$BACKUPNAME + echo "Backup DB" + {{- if .Values.mysql.enabled }} + drush -y sql-dump {{ .Values.drupal.backup.sqlDumpArgs }} --extra-dump=--no-tablespaces | gzip > /backup/$BACKUPNAME/db.sql.gz + {{- else }} + drush -y sql-dump {{ .Values.drupal.backup.sqlDumpArgs }} | gzip > /backup/$BACKUPNAME/db.sql.gz + {{- end }} + echo "Backup public files" + tar {{ .Values.drupal.backup.filesArgs }} -czvf /backup/$BACKUPNAME/files.tar.gz --directory=sites/default/files . + echo "Backup private files" + tar {{ .Values.drupal.backup.privateArgs }} -czvf /backup/$BACKUPNAME/private.tar.gz --directory=/private . + env: + {{- include "drupal.env" . | nindent 14 }} + {{- if .Values.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraEnvVars "context" $) | nindent 14 }} + {{- end }} + volumeMounts: + {{- include "drupal.volumeMounts" . | nindent 14 }} + {{- if .Values.drupal.volumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.drupal.volumeMounts "context" $) | nindent 14 }} + {{- end }} + {{- include "drupal.connectionPooler" . | nindent 10 }} + {{- if .Values.drupal.imagePullSecrets }} + imagePullSecrets: + {{- toYaml .Values.drupal.imagePullSecrets | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml .Values.drupal.securityContext | nindent 12 }} + volumes: + {{- include "drupal.volumes" . | nindent 10 }} + {{- include "drupal.connectionPooler.volumes" . | nindent 10 }} + - name: backup + {{- if .Values.drupal.backup.volume }} + {{- toYaml .Values.drupal.backup.volume | nindent 12 }} + {{- else }} + emptyDir: {} + {{- end }} +{{- end }} diff --git a/charts/drupal/templates/cronjob/drupal.yaml b/charts/drupal/templates/cronjob/drupal.yaml new file mode 100644 index 00000000..0238b66e --- /dev/null +++ b/charts/drupal/templates/cronjob/drupal.yaml @@ -0,0 +1,90 @@ +{{- if .Values.drupal.cron.enabled }} +{{- if semverCompare ">=1.21" $.Capabilities.KubeVersion.GitVersion }} +apiVersion: batch/v1 +{{- else }} +apiVersion: batch/v1beta1 +{{- end }} +kind: CronJob +metadata: + name: {{ template "drupal.fullname" . }}-drupal-cron + labels: + app.kubernetes.io/name: {{ include "drupal.name" . }} + helm.sh/chart: {{ include "drupal.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + schedule: "{{ .Values.drupal.cron.schedule }}" + startingDeadlineSeconds: 100 + concurrencyPolicy: Replace + successfulJobsHistoryLimit: {{ .Values.drupal.cron.successfulJobsHistoryLimit }} + failedJobsHistoryLimit: {{ .Values.drupal.cron.failedJobsHistoryLimit }} + jobTemplate: + spec: + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "drupal.name" . }} + helm.sh/chart: {{ include "drupal.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + annotations: + {{- if .Values.drupal.podAnnotations }} + {{- toYaml .Values.drupal.podAnnotations | nindent 12 }} + {{- end }} + spec: + serviceAccountName: {{ include "drupal.serviceAccountName" . }} + {{- if .Values.drupal.tolerations }} + tolerations: + {{- toYaml .Values.drupal.tolerations | nindent 10 }} + {{- end }} + {{- if .Values.drupal.nodeSelector }} + nodeSelector: + {{- toYaml .Values.drupal.nodeSelector | nindent 12 }} + {{- end }} + restartPolicy: OnFailure + containers: + - name: drush + image: "{{ .Values.drupal.image }}:{{ default .Chart.AppVersion .Values.drupal.tag }}" + imagePullPolicy: {{ default "" .Values.drupal.imagePullPolicy | quote }} + command: + - '/bin/sh' + - '-c' + - | + # Errors should fail the job + set -e + + # Pre Install scripts + {{- if .Values.drupal.cron.preInstallScripts }} + {{ .Values.drupal.cron.preInstallScripts | nindent 14}} + {{- end }} + + # Wait for DB to be available + until drush sql:query 'SHOW TABLES;'; do echo Waiting for DB; sleep 3; done + echo DB available + + # Check Drush status + drush status + + # Run cron + drush -y core-cron + env: + {{- include "drupal.env" . | nindent 14 }} + {{- if .Values.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraEnvVars "context" $) | nindent 14 }} + {{- end }} + volumeMounts: + {{- include "drupal.volumeMounts" . | nindent 14 }} + {{- if .Values.drupal.volumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.drupal.volumeMounts "context" $) | nindent 14 }} + {{- end }} + {{- include "drupal.connectionPooler" . | nindent 10 }} + {{- if .Values.drupal.imagePullSecrets }} + imagePullSecrets: + {{- toYaml .Values.drupal.imagePullSecrets | nindent 12 }} + {{- end }} + securityContext: + {{- toYaml .Values.drupal.securityContext | nindent 12 }} + volumes: + {{- include "drupal.volumes" . | nindent 10 }} + {{- include "drupal.connectionPooler.volumes" . | nindent 10 }} +{{- end }} diff --git a/charts/drupal/templates/deploy/drupal.yaml b/charts/drupal/templates/deploy/drupal.yaml new file mode 100644 index 00000000..5c4285c9 --- /dev/null +++ b/charts/drupal/templates/deploy/drupal.yaml @@ -0,0 +1,95 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "drupal.fullname" . }} + labels: + app.kubernetes.io/name: {{ include "drupal.name" . }} + helm.sh/chart: {{ include "drupal.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + replicas: {{ .Values.drupal.replicas }} + strategy: + type: RollingUpdate + selector: + matchLabels: + app.kubernetes.io/name: {{ include "drupal.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + tier: drupal + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "drupal.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + tier: drupal + annotations: + {{- if .Values.drupal.podAnnotations }} + {{- toYaml .Values.drupal.podAnnotations | nindent 8 }} + {{- end }} + checksum/config: {{ include (print $.Template.BasePath "/cm/drupal.yaml") . | sha256sum }} + spec: + serviceAccountName: {{ include "drupal.serviceAccountName" . }} + {{- if .Values.drupal.tolerations }} + tolerations: + {{- toYaml .Values.drupal.tolerations | nindent 8 }} + {{- end }} + {{- if .Values.drupal.nodeSelector }} + nodeSelector: + {{- toYaml .Values.drupal.nodeSelector | nindent 8 }} + {{- end }} + {{- if or (.Values.drupal.initContainers) (.Values.drupal.volumePermissions.enabled) (or (.Values.azure.azureFile.enabled) (.Values.azure.sharedDisk.enabled)) }} + initContainers: + {{- include "drupal.initContainers" . | nindent 8 }} + {{- end }} + containers: + - image: "{{ .Values.drupal.image }}:{{ default .Chart.AppVersion .Values.drupal.tag }}" + imagePullPolicy: {{ default "" .Values.drupal.imagePullPolicy | quote }} + {{- if .Values.drupal.command }} + command: {{- include "common.tplvalues.render" (dict "value" .Values.drupal.command "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.drupal.args }} + args: {{- include "common.tplvalues.render" (dict "value" .Values.drupal.args "context" $) | nindent 8 }} + {{- end }} + name: drupal + ports: + - containerPort: 9000 + name: tcp-php-fpm + protocol: TCP + {{- if .Values.drupal.healthcheck.enabled }} + livenessProbe: + exec: + command: + - php-fpm-healthcheck + initialDelaySeconds: 0 + periodSeconds: 5 + readinessProbe: + exec: + command: + - php-fpm-healthcheck + initialDelaySeconds: 1 + periodSeconds: 5 + {{- end }} + env: + {{- include "drupal.env" . | nindent 10 }} + {{- if .Values.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraEnvVars "context" $) | nindent 10 }} + {{- end }} + {{- if .Values.drupal.resources }} + resources: + {{- toYaml .Values.drupal.resources | nindent 10 }} + {{- end }} + volumeMounts: + {{- include "drupal.volumeMounts" . | nindent 10 }} + {{- if .Values.drupal.volumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.drupal.volumeMounts "context" $) | nindent 10 }} + {{- end }} + {{- include "drupal.connectionPooler" . | nindent 6 }} + {{- if .Values.drupal.imagePullSecrets }} + imagePullSecrets: + {{- toYaml .Values.drupal.imagePullSecrets | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.drupal.securityContext | nindent 8 }} + volumes: + {{- include "drupal.volumes" . | nindent 6 }} + {{- include "drupal.connectionPooler.volumes" . | nindent 6 }} diff --git a/drupal/templates/deploy/nginx.yaml b/charts/drupal/templates/deploy/nginx.yaml similarity index 64% rename from drupal/templates/deploy/nginx.yaml rename to charts/drupal/templates/deploy/nginx.yaml index d7b2a610..ab05f98e 100644 --- a/drupal/templates/deploy/nginx.yaml +++ b/charts/drupal/templates/deploy/nginx.yaml @@ -22,25 +22,25 @@ spec: app.kubernetes.io/name: {{ include "drupal.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} tier: frontend -{{- if .Values.nginx.podLabels }} -{{ toYaml .Values.nginx.podLabels | indent 8 }} -{{- end }} + {{- if .Values.nginx.podLabels }} + {{- toYaml .Values.nginx.podLabels | nindent 8 }} + {{- end }} annotations: -{{- if .Values.nginx.podAnnotations }} -{{ toYaml .Values.nginx.podAnnotations | indent 8 }} -{{- end }} + {{- if .Values.nginx.podAnnotations }} + {{- toYaml .Values.nginx.podAnnotations | nindent 8 }} + {{- end }} checksum/config: {{ include (print $.Template.BasePath "/cm/nginx.yaml") . | sha256sum }} spec: -{{- if .Values.nginx.tolerations }} + {{- if .Values.nginx.tolerations }} tolerations: -{{ toYaml .Values.nginx.tolerations | indent 6 }} -{{- end }} -{{- if .Values.nginx.nodeSelector }} + {{- toYaml .Values.nginx.tolerations | nindent 6 }} + {{- end }} + {{- if .Values.nginx.nodeSelector }} nodeSelector: -{{ toYaml .Values.nginx.nodeSelector | indent 8 }} -{{- end }} + {{- toYaml .Values.nginx.nodeSelector | nindent 8 }} + {{- end }} initContainers: -{{- if not (eq .Values.drupal.siteRoot "/") }} + {{- if not (eq .Values.drupal.siteRoot "/") }} - name: init-site-root image: 'alpine:3.10' command: @@ -52,14 +52,14 @@ spec: volumeMounts: - name: webroot mountPath: /webroot -{{- end }} + {{- end }} containers: - image: "{{ .Values.nginx.image }}:{{ default (print .Chart.AppVersion "-nginx") .Values.nginx.tag }}" imagePullPolicy: {{ default "" .Values.nginx.imagePullPolicy | quote }} name: nginx ports: - name: http - containerPort: 80 + containerPort: 8080 protocol: TCP - name: https containerPort: 443 @@ -67,66 +67,64 @@ spec: readinessProbe: httpGet: path: /_healthz - port: 80 + port: 8080 initialDelaySeconds: 0 periodSeconds: 5 livenessProbe: httpGet: path: /_healthz - port: 80 + port: 8080 initialDelaySeconds: 1 periodSeconds: 5 + {{- if .Values.nginx.resources }} resources: - requests: - memory: "200Mi" - cpu: "250m" - limits: - memory: "500Mi" - cpu: "400m" + {{- toYaml .Values.nginx.resources | nindent 10 }} + {{- end }} volumeMounts: - mountPath: /etc/nginx/nginx.conf name: cm-nginx readOnly: true subPath: nginx.conf -{{- if not .Values.drupal.disableDefaultFilesMount }} + {{- if not .Values.drupal.disableDefaultFilesMount }} - name: files mountPath: /var/www/html/sites/default/files subPath: public -{{- end }} -{{- if not (eq .Values.drupal.siteRoot "/") }} + {{- end }} + {{- if not (eq .Values.drupal.siteRoot "/") }} - name: webroot mountPath: /webroot -{{- end }} -{{- if .Values.nginx.volumeMounts }} -{{ toYaml .Values.nginx.volumeMounts | indent 8 }} -{{- end }} + {{- end }} + {{- if .Values.nginx.volumeMounts }} + {{- toYaml .Values.nginx.volumeMounts | nindent 8 }} + {{- end }} {{- if .Values.nginx.imagePullSecrets }} imagePullSecrets: -{{ toYaml .Values.nginx.imagePullSecrets | indent 8 }} + {{- toYaml .Values.nginx.imagePullSecrets | nindent 8 }} {{- end }} - # Allow non-root user to access PersistentVolume + {{- if .Values.nginx.securityContext }} securityContext: fsGroup: {{ .Values.nginx.securityContext.fsGroup }} + {{- end }} volumes: - name: cm-nginx configMap: name: {{ include "drupal.fullname" . }}-nginx -{{- if .Values.drupal.persistence.enabled }} + {{- if .Values.drupal.persistence.enabled }} - name: files persistentVolumeClaim: claimName: {{ template "drupal.fullname" . }}-drupal -{{- else if or (.Values.azure.azureFile.enabled) (.Values.azure.sharedDisk.enabled) }} + {{- else if or (.Values.azure.azureFile.enabled) (.Values.azure.sharedDisk.enabled) }} - name: files-public persistentVolumeClaim: claimName: {{ include "drupal.fullname" . }}-public -{{- else if not .Values.drupal.disableDefaultFilesMount }} + {{- else if not .Values.drupal.disableDefaultFilesMount }} - name: files emptyDir: {} -{{- end }} -{{- if not (eq .Values.drupal.siteRoot "/") }} + {{- end }} + {{- if not (eq .Values.drupal.siteRoot "/") }} - name: webroot emptyDir: {} -{{- end }} -{{- if .Values.nginx.volumes }} -{{ toYaml .Values.nginx.volumes | indent 6 }} -{{- end }} + {{- end }} + {{- if .Values.nginx.volumes }} + {{- toYaml .Values.nginx.volumes | nindent 6 }} + {{- end }} diff --git a/drupal/templates/hpa/drupal.yaml b/charts/drupal/templates/hpa/drupal.yaml similarity index 100% rename from drupal/templates/hpa/drupal.yaml rename to charts/drupal/templates/hpa/drupal.yaml diff --git a/drupal/templates/hpa/nginx.yaml b/charts/drupal/templates/hpa/nginx.yaml similarity index 100% rename from drupal/templates/hpa/nginx.yaml rename to charts/drupal/templates/hpa/nginx.yaml diff --git a/drupal/templates/ing/drupal.yaml b/charts/drupal/templates/ing/drupal.yaml similarity index 81% rename from drupal/templates/ing/drupal.yaml rename to charts/drupal/templates/ing/drupal.yaml index 8b1d0019..762e5917 100644 --- a/drupal/templates/ing/drupal.yaml +++ b/charts/drupal/templates/ing/drupal.yaml @@ -1,4 +1,4 @@ -{{- if .Values.ingress.enabled -}} +{{- if .Values.ingress.enabled }} {{- $fullName := include "drupal.fullname" . -}} {{- $releaseName := .Release.Name -}} {{- $varnishEnabled := .Values.varnish.enabled -}} @@ -16,24 +16,24 @@ metadata: helm.sh/chart: {{ include "drupal.chart" . }} app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- with .Values.ingress.annotations }} + {{- with .Values.ingress.annotations }} annotations: -{{ toYaml . | indent 4 }} -{{- end }} + {{- toYaml . | nindent 4 }} + {{- end }} spec: -{{- if .Values.ingress.className }} + {{- if .Values.ingress.className }} ingressClassName: {{ .Values.ingress.className }} -{{- end }} -{{- if .Values.ingress.tls }} + {{- end }} + {{- if .Values.ingress.tls }} tls: - {{- range .Values.ingress.tls }} + {{- range .Values.ingress.tls }} - hosts: {{- range .hosts }} - {{ . | quote }} {{- end }} secretName: {{ .secretName }} + {{- end }} {{- end }} -{{- end }} rules: {{- range .Values.ingress.hosts }} - host: {{ . | quote }} @@ -47,21 +47,21 @@ spec: service: name: {{ $releaseName }}-varnish port: - number: 80 + number: 8080 {{- else }} service: name: {{ $fullName }}-nginx port: - number: 80 + number: 8080 {{- end }} {{- else }} - backend: {{- if $varnishEnabled }} serviceName: {{ $releaseName }}-varnish - servicePort: 80 + servicePort: 8080 {{- else }} serviceName: {{ $fullName }}-nginx - servicePort: 80 + servicePort: 8080 {{- end }} {{- end }} {{- end }} diff --git a/charts/drupal/templates/job/post-install-site-install.yaml b/charts/drupal/templates/job/post-install-site-install.yaml new file mode 100644 index 00000000..5f2fdd21 --- /dev/null +++ b/charts/drupal/templates/job/post-install-site-install.yaml @@ -0,0 +1,188 @@ +{{- if .Values.drupal.install }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ template "drupal.fullname" . }}-site-install + labels: + app.kubernetes.io/name: {{ include "drupal.name" . }} + helm.sh/chart: {{ include "drupal.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + annotations: + "helm.sh/hook": post-install + "helm.sh/hook-weight": "10" + "helm.sh/hook-delete-policy": before-hook-creation +spec: + backoffLimit: {{ default "" .Values.drupal.backoffLimitInstall }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "drupal.name" . }} + helm.sh/chart: {{ include "drupal.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + annotations: + {{- if .Values.drupal.podAnnotations }} + {{- toYaml .Values.drupal.podAnnotations | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "drupal.serviceAccountName" . }} + {{- if .Values.drupal.tolerations }} + tolerations: + {{- toYaml .Values.drupal.tolerations | nindent 8 }} + {{- end }} + {{- if .Values.drupal.nodeSelector }} + nodeSelector: + {{- toYaml .Values.drupal.nodeSelector | nindent 8 }} + {{- end }} + restartPolicy: OnFailure + {{- if or (.Values.drupal.initContainers) (or (.Values.azure.azureFile.enabled) (.Values.azure.sharedDisk.enabled)) }} + initContainers: + {{- include "drupal.initContainers" . | nindent 8 }} + {{- end }} + containers: + - name: drush + image: "{{ .Values.drupal.image }}:{{ default .Chart.AppVersion .Values.drupal.tag }}" + imagePullPolicy: {{ default "" .Values.drupal.imagePullPolicy | quote }} + command: + - '/bin/sh' + - '-c' + - | + # Errors should fail the job + set -e + + # Pre Install scripts + {{- if .Values.drupal.preInstallScripts }} + {{ toYaml .Values.drupal.preInstallScripts | nindent 14}} + {{- end }} + + # Wait for DB to be available + {{ .Values.drupal.dbAvailabilityScript | nindent 14}} + + {{- if .Values.redis.enabled }} + {{- if .Values.redis.sentinel.enabled }} + until [[ $(printf "AUTH $REDIS_PASSWORD\r\n" | nc -w 2 {{ .Release.Name }}-redis {{ .Values.redis.sentinel.service.sentinelPort }}) == $(printf "+OK\r\n") ]]; do echo Waiting for Redis; sleep 3; done + {{- else }} + until [[ $(printf "AUTH $REDIS_PASSWORD\r\n" | nc -w 2 {{ .Release.Name }}-redis-master {{ .Values.redis.master.service.ports.redis }}) == $(printf "+OK\r\n") ]]; do echo Waiting for Redis; sleep 3; done + {{- end }} + echo Redis available + {{- end }} + + # Check Drush status + drush status || true + + {{- if .Values.redis.enabled }} + # Flush redis caches + {{- if .Values.redis.sentinel.enabled }} + printf "AUTH $REDIS_PASSWORD\r\nFLUSHDB\r\n" | nc -w 2 {{ .Release.Name }}-redis {{ .Values.redis.sentinel.service.sentinelPort }} + {{- else }} + printf "AUTH $REDIS_PASSWORD\r\nFLUSHDB\r\n" | nc -w 2 {{ .Release.Name }}-redis-master {{ .Values.redis.master.service.ports.redis }} + {{- end }} + {{- end }} + + # Run site install + {{- if .Values.drupal.restore.enabled }} + + # Check to see if using specific backup else use latest CHECK IF NAME SAYS LATEST + {{- if eq .Values.drupal.restore.name "latest"}} + BACKUPNAME=$(ls -td -- /backup/* | head -n 1 | sed -e "s/\/backup\///") + {{- else }} + BACKUPNAME='{{ .Values.drupal.restore.name }}' + {{- end }} + + echo "Restoring backup: $BACKUPNAME" + + {{- if .Values.drupal.restore.db }} + echo "Drop database" + drush sql-drop -y + echo "Restore database" + gunzip -c /backup/$BACKUPNAME/db.sql.gz{{ if .Values.drupal.restore.convert }} | sed 's/MyISAM/InnoDB/g'{{ end }} | drush sql-cli + echo "Database restored" + {{- end }} + + {{- if .Values.drupal.restore.files }} + echo "Deleting files" + # Errors from deleting should not fail the job + set +e + find sites/default/files/ -type f -print0 | xargs -0 rm + find sites/default/files/ -mindepth 1 -type d -print0 | xargs -0 rmdir + find /private/ -type f -print0 | xargs -0 rm + find /private/ -mindepth 1 -type d -print0 | xargs -0 rmdir + set -e + + echo "Restoring files" + {{- if .Values.drupal.restore.suppressTarErrors }} + set +e + {{- end }} + tar -zxf /backup/$BACKUPNAME/files.tar.gz --directory sites/default/files --no-acls --no-xattrs -m --no-same-permissions --no-overwrite-dir + tar -zxf /backup/$BACKUPNAME/private.tar.gz --directory /private --no-acls --no-xattrs -m --no-same-permissions --no-overwrite-dir + {{- if .Values.drupal.restore.suppressTarErrors }} + set -e + {{- end }} + echo "Files restored" + {{- end }} + + # Run database updates + {{- if .Values.drupal.cacheRebuildBeforeDatabaseMigration }} + drush -y cache:rebuild + {{- end }} + drush -y updatedb + + {{- else }} + time drush site:install {{ .Values.drupal.profile }} \ + --sites-subdir=default \ + {{- if .Values.mysql.enabled }} + --db-url="mysql://{{ .Values.mysql.auth.username }}:$MYSQL_PASSWORD@{{ .Release.Name }}-mysql:{{ .Values.mysql.primary.service.ports.mysql }}/{{ .Values.mysql.auth.database }}" \ + {{- else if .Values.postgresql.enabled }} + --db-url="pgsql://{{ .Values.postgresql.auth.username }}:$POSTGRES_PASSWORD@{{ .Release.Name }}-postgresql:{{ .Values.postgresql.primary.service.ports.postgresql }}/{{ .Values.postgresql.auth.database }}" \ + {{- end }} + --account-name={{ .Values.drupal.username }} \ + --account-pass=$DRUPAL_ADMIN_PASSWORD \ + --site-mail={{ .Values.drupal.siteEmail | quote }} \ + --site-name={{ .Values.drupal.siteName | quote }} \ + {{- if .Values.drupal.extensions.enabled }} + wxt_extension_configure_form.select_all='TRUE' \ + {{- end }} + install_configure_form.update_status_module='array(FALSE,FALSE)' \ + --yes + {{- end }} + + drush -y cache:rebuild + + {{- if .Values.redis.enabled }} + # Enable redis + drush -y pm:enable redis + {{- end }} + + # Rebuild caches + drush -y cache:rebuild + + # Extra installation scripts + {{- if .Values.drupal.postInstallScripts }} + {{ toYaml .Values.drupal.postInstallScripts | nindent 14}} + {{- end }} + env: + {{- include "drupal.env" . | nindent 10 }} + {{- if .Values.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraEnvVars "context" $) | nindent 10 }} + {{- end }} + volumeMounts: + {{- include "drupal.volumeMounts" . | nindent 10 }} + {{- if .Values.drupal.volumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.drupal.volumeMounts "context" $) | nindent 10 }} + {{- end }} + {{- include "drupal.connectionPooler" . | nindent 6 }} + {{- if .Values.drupal.imagePullSecrets }} + imagePullSecrets: + {{- toYaml .Values.drupal.imagePullSecrets | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.drupal.securityContext | nindent 8 }} + volumes: + {{- include "drupal.volumes" . | nindent 6 }} + {{- include "drupal.connectionPooler.volumes" . | nindent 6 }} + {{- if .Values.drupal.restore.enabled }} + - name: backup + {{- toYaml .Values.drupal.restore.volume | nindent 8 }} + {{- end }} +{{- end }} diff --git a/charts/drupal/templates/job/post-upgrade-reconfigure.yaml b/charts/drupal/templates/job/post-upgrade-reconfigure.yaml new file mode 100644 index 00000000..20fe1a40 --- /dev/null +++ b/charts/drupal/templates/job/post-upgrade-reconfigure.yaml @@ -0,0 +1,109 @@ +{{- if .Values.drupal.reconfigure }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ template "drupal.fullname" . }}-reconfigure + labels: + app.kubernetes.io/name: {{ include "drupal.name" . }} + helm.sh/chart: {{ include "drupal.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + annotations: + "helm.sh/hook": post-upgrade + "helm.sh/hook-weight": "10" + "helm.sh/hook-delete-policy": before-hook-creation +spec: + backoffLimit: {{ default "" .Values.drupal.backoffLimitReconfigure }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "drupal.name" . }} + helm.sh/chart: {{ include "drupal.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + annotations: + {{- if .Values.drupal.podAnnotations }} + {{- toYaml .Values.drupal.podAnnotations | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "drupal.serviceAccountName" . }} + {{- if .Values.drupal.tolerations }} + tolerations: + {{- toYaml .Values.drupal.tolerations | nindent 8 }} + {{- end }} + {{- if .Values.drupal.nodeSelector }} + nodeSelector: + {{- toYaml .Values.drupal.nodeSelector | nindent 8 }} + {{- end }} + restartPolicy: OnFailure + {{- if or (.Values.drupal.initContainers) (or (.Values.azure.azureFile.enabled) (.Values.azure.sharedDisk.enabled)) }} + initContainers: + {{- include "drupal.initContainers" . | nindent 8 }} + {{- end }} + containers: + - name: drush + image: "{{ .Values.drupal.image }}:{{ default .Chart.AppVersion .Values.drupal.tag }}" + imagePullPolicy: {{ default "" .Values.drupal.imagePullPolicy | quote }} + command: + - '/bin/sh' + - '-c' + - | + # Errors should fail the job + set -e + + # Pre Upgrade scripts + {{- if .Values.drupal.preUpgradeScripts }} + {{ toYaml .Values.drupal.preUpgradeScripts | nindent 14}} + {{- end }} + + # Wait for DB to be available + {{ .Values.drupal.dbAvailabilityScript | nindent 14}} + + {{- if .Values.redis.enabled }} + {{- if .Values.redis.sentinel.enabled }} + until [[ $(printf "AUTH $REDIS_PASSWORD\r\n" | nc -w 2 {{ .Release.Name }}-redis {{ .Values.redis.sentinel.service.sentinelPort }}) == $(printf "+OK\r\n") ]]; do echo Waiting for Redis; sleep 3; done + {{- else }} + until [[ $(printf "AUTH $REDIS_PASSWORD\r\n" | nc -w 2 {{ .Release.Name }}-redis-master {{ .Values.redis.master.service.ports.redis }}) == $(printf "+OK\r\n") ]]; do echo Waiting for Redis; sleep 3; done + {{- end }} + echo Redis available + {{- end }} + + # Check Drush status + drush status || true + + # Run database updates + {{- if .Values.drupal.cacheRebuildBeforeDatabaseMigration }} + drush -y cache:rebuild + {{- end }} + {{- if .Values.drupal.updateDBBeforeDatabaseMigration }} + drush -y updatedb + {{- end }} + + # Rebuild caches + drush -y cache:rebuild + + # Post Upgrade scripts + {{- if .Values.drupal.postUpgradeScripts }} + {{ toYaml .Values.drupal.postUpgradeScripts | nindent 14}} + {{- end }} + env: + {{- include "drupal.env" . | nindent 10 }} + {{- if .Values.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraEnvVars "context" $) | nindent 10 }} + {{- end }} + volumeMounts: + {{- include "drupal.volumeMounts" . | nindent 10 }} + {{- if .Values.drupal.volumeMounts }} + {{- include "common.tplvalues.render" (dict "value" .Values.drupal.volumeMounts "context" $) | nindent 10 }} + {{- end }} + {{- include "drupal.connectionPooler" . | nindent 6 }} + {{- if .Values.drupal.imagePullSecrets }} + imagePullSecrets: + {{- toYaml .Values.drupal.imagePullSecrets | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.drupal.securityContext | nindent 8 }} + volumes: + {{- include "drupal.volumes" . | nindent 6 }} + {{- include "drupal.connectionPooler.volumes" . | nindent 6 }} +{{- end }} diff --git a/charts/drupal/templates/netpol/drupal.yaml b/charts/drupal/templates/netpol/drupal.yaml new file mode 100644 index 00000000..d3c7ca33 --- /dev/null +++ b/charts/drupal/templates/netpol/drupal.yaml @@ -0,0 +1,16 @@ +{{- if .Values.netpol.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "drupal.fullname" . }}-allow-same-ns + labels: + app.kubernetes.io/name: {{ include "drupal.name" . }} + helm.sh/chart: {{ include "drupal.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + podSelector: {} + ingress: + - from: + - podSelector: {} +{{- end }} diff --git a/charts/drupal/templates/netpol/route.yaml b/charts/drupal/templates/netpol/route.yaml new file mode 100644 index 00000000..d2eb8ccb --- /dev/null +++ b/charts/drupal/templates/netpol/route.yaml @@ -0,0 +1,20 @@ +{{- if .Values.netpol.openshift.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "drupal.fullname" . }}-allow-openshift-ingress + labels: + app.kubernetes.io/name: {{ include "drupal.name" . }} + helm.sh/chart: {{ include "drupal.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + ingress: + - from: + - namespaceSelector: + matchLabels: + network.openshift.io/policy-group: ingress + podSelector: {} + policyTypes: + - Ingress +{{- end }} diff --git a/drupal/templates/pdb/poddisruptionbudget.yaml b/charts/drupal/templates/pdb/poddisruptionbudget.yaml similarity index 100% rename from drupal/templates/pdb/poddisruptionbudget.yaml rename to charts/drupal/templates/pdb/poddisruptionbudget.yaml diff --git a/charts/drupal/templates/pv/csi-azure-file.yaml b/charts/drupal/templates/pv/csi-azure-file.yaml new file mode 100644 index 00000000..f94f0a16 --- /dev/null +++ b/charts/drupal/templates/pv/csi-azure-file.yaml @@ -0,0 +1,42 @@ + +{{- $name := include "drupal.name" . -}} +{{- $fullName := include "drupal.fullname" . -}} +{{- $chartName := include "drupal.chart" . -}} +{{- $chart := .Chart }} +{{- $release := .Release }} +{{- $values := .Values }} +{{- $ctx := . }} +{{- range $k, $v := .Values.azure.azureFile.folders }} +{{- if $values.azure.azureFile.enabled -}} +{{- if not $values.azure.azureFile.disablePVCreation }} +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + {{- if $values.azure.azureFile.annotations }} + annotations: + {{- toYaml $values.azure.azureFile.annotations | nindent 4 }} + {{- end }} + name: {{ $fullName }}-{{ $v }} +spec: + capacity: + storage: {{ $values.azure.azureFile.size }} + accessModes: + - {{ $values.azure.azureFile.accessMode }} + {{- if $values.azure.storageClass.create }} + storageClassName: {{ $fullName }}-csi-azure + {{- else if eq "-" $values.azure.azureFile.storageClass }} + storageClassName: "" + {{- else if $values.azure.azureFile.storageClass }} + storageClassName: "{{ $values.azure.azureFile.storageClass }}" + {{- end }} + {{- if $values.azure.azureFile.backup.spec }} + {{- toYaml $values.azure.azureFile.backup.spec | nindent 2 }} + {{- end }} + {{- if $values.azure.azureFile.backup.mountOptions }} + mountOptions: + {{- toYaml $values.azure.azureFile.backup.mountOptions | nindent 4 }} + {{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/drupal/templates/pv/csi-azure-shared-disk.yaml b/charts/drupal/templates/pv/csi-azure-shared-disk.yaml new file mode 100644 index 00000000..cae0d50f --- /dev/null +++ b/charts/drupal/templates/pv/csi-azure-shared-disk.yaml @@ -0,0 +1,41 @@ +{{- $name := include "drupal.name" . -}} +{{- $fullName := include "drupal.fullname" . -}} +{{- $chartName := include "drupal.chart" . -}} +{{- $chart := .Chart }} +{{- $release := .Release }} +{{- $values := .Values }} +{{- $ctx := . }} +{{- range $k, $v := .Values.azure.sharedDisk.folders }} +{{- if $values.azure.sharedDisk.enabled }} +{{- if not $values.azure.sharedDisk.disablePVCreation }} +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + {{- if $values.azure.sharedDisk.annotations }} + annotations: + {{- toYaml $values.azure.sharedDisk.annotations | nindent 4 }} + {{- end }} + name: {{ $fullName }}-{{ $v }} +spec: + capacity: + storage: {{ $values.azure.sharedDisk.size }} + accessModes: + - {{ $values.azure.sharedDisk.accessMode }} + {{- if $values.azure.storageClass.create }} + storageClassName: {{ $fullName }}-csi-azure + {{- else if eq "-" $values.azure.sharedDisk.storageClass }} + storageClassName: "" + {{- else if $values.azure.sharedDisk.storageClass }} + storageClassName: "{{ $values.azure.sharedDisk.storageClass }}" + {{- end }} + {{- if $values.azure.sharedDisk.private.spec }} + {{- toYaml $values.azure.sharedDisk.private.spec | nindent 2 }} + {{- end }} + {{- if $values.azure.sharedDisk.private.mountOptions }} + mountOptions: + {{- toYaml $values.azure.sharedDisk.private.mountOptions | nindent 4 }} + {{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/drupal/templates/pvc/csi-azure-file.yaml b/charts/drupal/templates/pvc/csi-azure-file.yaml new file mode 100644 index 00000000..12c35612 --- /dev/null +++ b/charts/drupal/templates/pvc/csi-azure-file.yaml @@ -0,0 +1,36 @@ +{{- $name := include "drupal.name" . -}} +{{- $fullName := include "drupal.fullname" . -}} +{{- $chartName := include "drupal.chart" . -}} +{{- $chart := .Chart }} +{{- $release := .Release }} +{{- $values := .Values }} +{{- $ctx := . }} +{{- range $k, $v := .Values.azure.azureFile.folders }} +{{- if $values.azure.azureFile.enabled }} +--- +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + annotations: + {{- if $values.azure.azureFile.enabled }} + {{- toYaml $values.azure.azureFile.annotations | nindent 4 }} + {{- end }} + name: {{ $fullName }}-{{ $v }} +spec: + accessModes: + - {{ $values.azure.azureFile.accessMode }} + resources: + requests: + storage: {{ $values.azure.azureFile.size }} + {{- if not $values.azure.azureFile.disableVolumeName }} + volumeName: {{ $fullName }}-{{ $v }} + {{- end }} + {{- if $values.azure.storageClass.create }} + storageClassName: {{ $fullName }}-csi-azure + {{- else if eq "-" $values.azure.azureFile.storageClass }} + storageClassName: "" + {{- else if $values.azure.azureFile.storageClass }} + storageClassName: "{{ $values.azure.azureFile.storageClass }}" + {{- end }} +{{- end }} +{{- end }} diff --git a/charts/drupal/templates/pvc/csi-azure-shared-disk.yaml b/charts/drupal/templates/pvc/csi-azure-shared-disk.yaml new file mode 100644 index 00000000..e7b6134d --- /dev/null +++ b/charts/drupal/templates/pvc/csi-azure-shared-disk.yaml @@ -0,0 +1,36 @@ +{{- $name := include "drupal.name" . -}} +{{- $fullName := include "drupal.fullname" . -}} +{{- $chartName := include "drupal.chart" . -}} +{{- $chart := .Chart }} +{{- $release := .Release }} +{{- $values := .Values }} +{{- $ctx := . }} +{{- range $k, $v := .Values.azure.sharedDisk.folders }} +{{- if $values.azure.sharedDisk.enabled }} +--- +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + annotations: + {{- if $values.azure.azureFile.enabled }} + {{- toYaml $values.azure.azureFile.annotations | nindent 4 }} + {{- end }} + name: {{ $fullName }}-{{ $v }} +spec: + accessModes: + - {{ $values.azure.sharedDisk.accessMode }} + resources: + requests: + storage: {{ $values.azure.sharedDisk.size }} + {{- if not $values.azure.sharedDisk.disableVolumeName }} + volumeName: {{ $fullName }}-{{ $v }} + {{- end }} + {{- if $values.azure.storageClass.create }} + storageClassName: {{ $fullName }}-csi-azure + {{- else if eq "-" $values.azure.sharedDisk.storageClass }} + storageClassName: "" + {{- else if $values.azure.sharedDisk.storageClass }} + storageClassName: "{{ $values.azure.sharedDisk.storageClass }}" + {{- end }} +{{- end }} +{{- end }} diff --git a/drupal/templates/pvc/drupal.yaml b/charts/drupal/templates/pvc/drupal.yaml similarity index 74% rename from drupal/templates/pvc/drupal.yaml rename to charts/drupal/templates/pvc/drupal.yaml index 9a3421df..a59455db 100644 --- a/drupal/templates/pvc/drupal.yaml +++ b/charts/drupal/templates/pvc/drupal.yaml @@ -2,10 +2,10 @@ kind: PersistentVolumeClaim apiVersion: v1 metadata: -{{- if .Values.drupal.persistence.annotations }} + {{- if .Values.drupal.persistence.annotations }} annotations: -{{ toYaml .Values.drupal.persistence.annotations | indent 4 }} -{{- end }} + {{- toYaml .Values.drupal.persistence.annotations | nindent 4 }} + {{- end }} name: {{ include "drupal.fullname" . }}-drupal labels: app.kubernetes.io/name: {{ include "drupal.name" . }}-drupal @@ -21,11 +21,11 @@ spec: {{- if .Values.drupal.persistence.iops }} iops: {{ .Values.drupal.persistence.iops | quote }} {{- end }} -{{- if .Values.drupal.persistence.storageClass }} -{{- if (eq "-" .Values.drupal.persistence.storageClass) }} + {{- if .Values.drupal.persistence.storageClass }} + {{- if (eq "-" .Values.drupal.persistence.storageClass) }} storageClassName: "" -{{- else }} + {{- else }} storageClassName: "{{ .Values.drupal.persistence.storageClass }}" -{{- end }} -{{- end }} + {{- end }} + {{- end }} {{- end }} diff --git a/charts/drupal/templates/sa/drupal.yaml b/charts/drupal/templates/sa/drupal.yaml new file mode 100644 index 00000000..aff4dd46 --- /dev/null +++ b/charts/drupal/templates/sa/drupal.yaml @@ -0,0 +1,12 @@ +{{- if .Values.drupal.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "drupal.serviceAccountName" . }} + labels: + app.kubernetes.io/name: {{ include "drupal.name" . }} + helm.sh/chart: {{ include "drupal.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +automountServiceAccountToken: {{ .Values.drupal.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/drupal/templates/secret/drupal.yaml b/charts/drupal/templates/secret/drupal.yaml similarity index 93% rename from drupal/templates/secret/drupal.yaml rename to charts/drupal/templates/secret/drupal.yaml index 2251febe..99bad0d6 100644 --- a/drupal/templates/secret/drupal.yaml +++ b/charts/drupal/templates/secret/drupal.yaml @@ -1,3 +1,4 @@ +{{- if not .Values.drupal.usePasswordFiles }} apiVersion: v1 kind: Secret metadata: @@ -22,3 +23,4 @@ data: {{ if .Values.external.enabled }} databasePassword: {{ .Values.external.password | b64enc | quote }} {{ end }} +{{- end }} diff --git a/drupal/templates/secret/pgbouncer.yaml b/charts/drupal/templates/secret/pgbouncer.yaml similarity index 100% rename from drupal/templates/secret/pgbouncer.yaml rename to charts/drupal/templates/secret/pgbouncer.yaml diff --git a/drupal/templates/secret/proxysql.yaml b/charts/drupal/templates/secret/proxysql.yaml similarity index 100% rename from drupal/templates/secret/proxysql.yaml rename to charts/drupal/templates/secret/proxysql.yaml diff --git a/drupal/templates/secret/ssmtp.yaml b/charts/drupal/templates/secret/ssmtp.yaml similarity index 100% rename from drupal/templates/secret/ssmtp.yaml rename to charts/drupal/templates/secret/ssmtp.yaml diff --git a/drupal/templates/storageclass/csi-azure.yaml b/charts/drupal/templates/storageclass/csi-azure.yaml similarity index 100% rename from drupal/templates/storageclass/csi-azure.yaml rename to charts/drupal/templates/storageclass/csi-azure.yaml diff --git a/drupal/templates/svc/drupal.yaml b/charts/drupal/templates/svc/drupal.yaml similarity index 92% rename from drupal/templates/svc/drupal.yaml rename to charts/drupal/templates/svc/drupal.yaml index 6df804aa..37f1c2c6 100644 --- a/drupal/templates/svc/drupal.yaml +++ b/charts/drupal/templates/svc/drupal.yaml @@ -16,4 +16,4 @@ spec: app.kubernetes.io/name: {{ include "drupal.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} tier: drupal - type: {{ .Values.drupal.serviceType }} + type: {{ .Values.drupal.serviceType }} diff --git a/drupal/templates/svc/nginx.yaml b/charts/drupal/templates/svc/nginx.yaml similarity index 97% rename from drupal/templates/svc/nginx.yaml rename to charts/drupal/templates/svc/nginx.yaml index 16cfcd84..8429fae9 100644 --- a/drupal/templates/svc/nginx.yaml +++ b/charts/drupal/templates/svc/nginx.yaml @@ -10,7 +10,7 @@ metadata: spec: ports: - name: http - port: 80 + port: 8080 targetPort: http - name: https port: 443 diff --git a/drupal/values.yaml b/charts/drupal/values.yaml similarity index 90% rename from drupal/values.yaml rename to charts/drupal/values.yaml index 17b48b08..f4523833 100644 --- a/drupal/values.yaml +++ b/charts/drupal/values.yaml @@ -15,6 +15,15 @@ ingress: # hosts: # - chart-example.local +extraEnvVars: [] + +netpol: + enabled: false + openshift: + enabled: false + +## Configuration values for the Drupal chart +## ref: https://github.com/drupalwxt/helm-drupal/blob/master/README.md drupal: ## Drupal image version ## ref: https://hub.docker.com/drupalwxt/site-wxt/tags/ @@ -38,11 +47,15 @@ drupal: replicas: 1 - # PHP configuration php: ini: {} # max_execution_time: 300 + fpm: |- + pm.max_children = 50 + pm.start_servers = 5 + pm.min_spare_servers = 5 + pm.max_spare_servers = 35 ## User of the application ## @@ -64,7 +77,7 @@ drupal: # Default WxT Library theme (only used if install and/or reconfigure are enabled) # Common options include: theme-wet-boew, theme-gcweb-legacy, theme-gcweb, ... - wxtTheme: theme-gcweb + theme: theme-gcweb ## Version of the application ## @@ -101,12 +114,22 @@ drupal: ## Extra CLI scripts ## - extraInstallScripts: '' + preInstallScripts: '' + # |- + # drush config-set system.performance js.preprocess 0 -y; + # drush config-set system.performance css.preprocess 0 -y; + + postInstallScripts: '' + # |- + # drush config-set system.performance js.preprocess 0 -y; + # drush config-set system.performance css.preprocess 0 -y; + + preUpgradeScripts: '' # |- # drush config-set system.performance js.preprocess 0 -y; # drush config-set system.performance css.preprocess 0 -y; - extraUpgradeScripts: '' + postUpgradeScripts: '' # |- # drush config-set system.performance js.preprocess 0 -y; # drush config-set system.performance css.preprocess 0 -y; @@ -142,9 +165,6 @@ drupal: cacheRebuildBeforeDatabaseMigration: true updateDBBeforeDatabaseMigration: true - # Run WxT specific commands - wxtUpdate: false - # Restrict how many attempt install and/or reconfigure jobs will try in case of failure. Default is 6. # backoffLimitInstall: 1 # backoffLimitReconfigure: 1 @@ -162,6 +182,14 @@ drupal: # Defaults to once an hour schedule: '0 * * * *' + preInstallScripts: '' + # |- + # drush config-set system.performance js.preprocess 0 -y; + # drush config-set system.performance css.preprocess 0 -y; + + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 1 + additionalCrons: {} # example: # # Run at midnight UTC @@ -245,10 +273,10 @@ drupal: # name: nothing # readOnly: true - securityContext: - fsGroup: 82 - runAsUser: 82 - runAsGroup: 82 + securityContext: {} + # fsGroup: 82 + # runAsUser: 82 + # runAsGroup: 82 smtp: host: mail @@ -281,6 +309,24 @@ drupal: volumePermissions: enabled: false + ## Drupal pods ServiceAccount + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ + ## + serviceAccount: + ## @param serviceAccount.create Enable the creation of a ServiceAccount for Drupal pods + ## + create: true + ## @param serviceAccount.name Name of the created ServiceAccount + ## If not set and create is true, a name is generated using the drupal.fullname template + ## + name: "" + ## @param serviceAccount.annotations Annotations for Drupal Service Account + ## + annotations: {} + ## @param serviceAccount.automountServiceAccountToken Automount service account token for the server service account + ## + automountServiceAccountToken: true + # Set an initContainers manually # initContainers: # - name: set-volume-permissions @@ -317,6 +363,12 @@ drupal: targetCPUUtilizationPercentage: 50 targetMemoryUtilizationPercentage: 50 + command: [] + + args: [] + +## Configuration values for the Drupal chart +## ref: https://github.com/drupalwxt/helm-drupal/blob/master/README.md nginx: ## Nginx image version ## ref: https://hub.docker.com/drupalwxt/site-wxt/tags/ @@ -353,14 +405,21 @@ nginx: # name: nothing # readOnly: true - securityContext: - enabled: true - fsGroup: 33 + securityContext: {} + # fsGroup: 33 gzip: true client_max_body_size: 20m real_ip_header: X-Forwarded-For + resources: {} + # requests: + # memory: "200Mi" + # cpu: "250m" + # limits: + # memory: "500Mi" + # cpu: "400m" + # Example of using both toleration and nodeSelector to deploy nginx on an AKS Spot instance # node pool: tolerations: [] @@ -403,6 +462,7 @@ azure: # Azure File logic azureFile: enabled: false + folders: ["backup", "private", "public", "tmp"] # Uncomment next line if you want to disable specifying a volume name on the public and private PVCs # disableVolumeName: true @@ -526,6 +586,7 @@ azure: # Shared Disk logic sharedDisk: enabled: false + folders: ["private", "public"] # Uncomment next line if you want to disable specifying a volume name on the public and private PVCs # disableVolumeName: true @@ -610,6 +671,7 @@ mysql: slow_query_log=0 slow_query_log_file=/opt/bitnami/mysql/logs/mysqld.log long_query_time=10.0 + transaction_isolation="READ-COMMITTED" max_allowed_packet = 256M innodb_buffer_pool_size = 4096M @@ -617,11 +679,13 @@ mysql: table_definition_cache = 4096 table_open_cache = 8192 innodb_flush_log_at_trx_commit=2 + [client] port=3306 socket=/opt/bitnami/mysql/tmp/mysql.sock default-character-set=UTF8 plugin_dir=/opt/bitnami/mysql/lib/plugin + [manager] port=3306 socket=/opt/bitnami/mysql/tmp/mysql.sock @@ -707,8 +771,23 @@ redis: # Disable RDB persistence. save "" +## Configuration values for the Solr dependency sub-chart +## ref: https://github.com/bitnami/charts/blob/master/bitnami/redis/README.md +solr: + enabled: false + image: + registry: docker.io + repository: bitnami/solr + tag: 9.2.1-debian-11-r16 + cloudEnabled: false + cloudBootstrap: false + zookeeper: + enabled: false + replicaCount: 1 + collectionReplicas: 1 + ## Configuration values for the Varnish dependency sub-chart -## ref: https://github.com/StatCan/charts/blob/master/stable/varnish/README.md +## ref: https://github.com/statcan/charts/blob/master/stable/varnish/README.md varnish: enabled: false varnishd: @@ -748,7 +827,7 @@ varnish: backend nginx { .host = "{{ include "backend.fullname" . }}-nginx"; .host_header = "{{ include "backend.fullname" . }}-nginx"; - .port = "80"; + .port = "8080"; } sub vcl_init { @@ -947,3 +1026,6 @@ varnish: # synthetic(std.fileread("/data/configuration/varnish/errors/503.html")); # return (deliver); # } + +solr: + enabled: false diff --git a/solr/.helmignore b/charts/solr/.helmignore similarity index 100% rename from solr/.helmignore rename to charts/solr/.helmignore diff --git a/solr/Chart.yaml b/charts/solr/Chart.yaml similarity index 100% rename from solr/Chart.yaml rename to charts/solr/Chart.yaml diff --git a/solr/README.md b/charts/solr/README.md similarity index 100% rename from solr/README.md rename to charts/solr/README.md diff --git a/drupal7/charts/.gitkeep b/charts/solr/charts/.gitkeep similarity index 100% rename from drupal7/charts/.gitkeep rename to charts/solr/charts/.gitkeep diff --git a/solr/templates/NOTES.txt b/charts/solr/templates/NOTES.txt similarity index 100% rename from solr/templates/NOTES.txt rename to charts/solr/templates/NOTES.txt diff --git a/solr/templates/_helpers.tpl b/charts/solr/templates/_helpers.tpl similarity index 100% rename from solr/templates/_helpers.tpl rename to charts/solr/templates/_helpers.tpl diff --git a/solr/templates/dr/solr.yaml b/charts/solr/templates/dr/solr.yaml similarity index 100% rename from solr/templates/dr/solr.yaml rename to charts/solr/templates/dr/solr.yaml diff --git a/solr/templates/ing/solr.yaml b/charts/solr/templates/ing/solr.yaml similarity index 100% rename from solr/templates/ing/solr.yaml rename to charts/solr/templates/ing/solr.yaml diff --git a/solr/templates/solrcloud/solr.yaml b/charts/solr/templates/solrcloud/solr.yaml similarity index 100% rename from solr/templates/solrcloud/solr.yaml rename to charts/solr/templates/solrcloud/solr.yaml diff --git a/solr/values.yaml b/charts/solr/values.yaml similarity index 100% rename from solr/values.yaml rename to charts/solr/values.yaml diff --git a/drupal7/.helmignore b/charts/varnish/.helmignore similarity index 97% rename from drupal7/.helmignore rename to charts/varnish/.helmignore index f0c13194..50af0317 100644 --- a/drupal7/.helmignore +++ b/charts/varnish/.helmignore @@ -19,3 +19,4 @@ .project .idea/ *.tmproj +.vscode/ diff --git a/charts/varnish/Chart.yaml b/charts/varnish/Chart.yaml new file mode 100644 index 00000000..bc51e0d3 --- /dev/null +++ b/charts/varnish/Chart.yaml @@ -0,0 +1,15 @@ +apiVersion: v2 +type: application +description: A Helm chart for using Varnish. +name: varnish +version: 0.2.5 +appVersion: 6.6.0 +home: https://www.varnish-software.com +sources: +- https://github.com/varnish +maintainers: +- name: sylus + email: william.hearn@canada.ca +- name: zachomedia + email: zachary.seguin@canada.ca +engine: gotpl diff --git a/charts/varnish/README.md b/charts/varnish/README.md new file mode 100644 index 00000000..7c7e0a08 --- /dev/null +++ b/charts/varnish/README.md @@ -0,0 +1,14 @@ +# Varnish Helm Chart + +This chart installs a Varnish deamon which can be used as a proxy to cache static web resources. + +## Prerequisites Details + +* Kubernetes 1.8+ + +## Chart Details + +This chart will do the following: + +* Kubernetes Deployment +* ConfigMap with `default.vcl` for configuration of Varnish diff --git a/charts/varnish/templates/NOTES.txt b/charts/varnish/templates/NOTES.txt new file mode 100644 index 00000000..d70b3212 --- /dev/null +++ b/charts/varnish/templates/NOTES.txt @@ -0,0 +1,2 @@ + +Point your Ingress Controller to the {{ include "varnish.fullname" . }} service diff --git a/drupal/templates/_helpers.tpl b/charts/varnish/templates/_helpers.tpl similarity index 62% rename from drupal/templates/_helpers.tpl rename to charts/varnish/templates/_helpers.tpl index 474f42c1..30c20f12 100644 --- a/drupal/templates/_helpers.tpl +++ b/charts/varnish/templates/_helpers.tpl @@ -2,7 +2,7 @@ {{/* Expand the name of the chart. */}} -{{- define "drupal.name" -}} +{{- define "varnish.name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} {{- end -}} @@ -11,7 +11,7 @@ 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 "drupal.fullname" -}} +{{- define "varnish.fullname" -}} {{- if .Values.fullnameOverride -}} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} {{- else -}} @@ -25,22 +25,21 @@ If release name contains chart name it will be used as a full name. {{- 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. +Create chart name and version as used by the chart label. */}} -{{- define "backend.fullname" -}} -{{- $name := default "drupal" .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} +{{- define "varnish.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} {{- end -}} {{/* -Create chart name and version as used by the chart label. +Common labels */}} -{{- define "drupal.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- define "varnish.labels" -}} +app.kubernetes.io/name: {{ include "varnish.name" . }} +helm.sh/chart: {{ include "varnish.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} {{- end -}} diff --git a/charts/varnish/templates/configmap/varnish.yaml b/charts/varnish/templates/configmap/varnish.yaml new file mode 100644 index 00000000..68640705 --- /dev/null +++ b/charts/varnish/templates/configmap/varnish.yaml @@ -0,0 +1,32 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: "{{ include "varnish.fullname" . }}" + labels: +{{ include "varnish.labels" . | indent 4 }} +data: +{{- if .Values.varnishConfigContent }} + default.vcl: | +{{ tpl .Values.varnishConfigContent . | indent 4 }} +{{- else }} + default.vcl: | + vcl 4.0; + + # Varnish configuration was not provided to the helm chart. + # Please provide `varnishConfigContent` + + backend placeholder { + .host = "localhost"; + .port = "80"; + } + + sub vcl_recv { + return (synth(700, "Service Unavailable")); + } + + sub vcl_synth { + set resp.status = 503; + return (deliver); + } + +{{- end }} diff --git a/charts/varnish/templates/deploy/varnish.yaml b/charts/varnish/templates/deploy/varnish.yaml new file mode 100644 index 00000000..256eccea --- /dev/null +++ b/charts/varnish/templates/deploy/varnish.yaml @@ -0,0 +1,96 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "varnish.fullname" . }} + labels: +{{ include "varnish.labels" . | indent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "varnish.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "varnish.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + annotations: +{{- if .Values.annotations }} +{{ toYaml .Values.annotations | indent 8 }} +{{- end }} + checksum/config: {{ include (print $.Template.BasePath "/configmap/varnish.yaml") . | sha256sum }} +{{- if .Values.admin.enabled }} + checksum/secret: {{ include (print $.Template.BasePath "/secret/varnish.yaml") . | sha256sum }} +{{- end }} + spec: +{{- if .Values.tolerations }} + tolerations: +{{ toYaml .Values.tolerations | indent 6 }} +{{- end }} +{{- if .Values.nodeSelector }} + nodeSelector: +{{ toYaml .Values.nodeSelector | indent 8 }} +{{- end }} + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.varnishd.image }}:{{ default .Chart.AppVersion .Values.varnishd.tag }}" + imagePullPolicy: {{ .Values.varnishd.pullPolicy }} + command: + - varnishd + - -F + - -f + - /etc/varnish/default.vcl + - -a + - http=:{{ .Values.service.port }},HTTP +{{- if .Values.admin.enabled }} + - -T + - 0.0.0.0:{{ .Values.admin.port }} + - -S + - /etc/varnish/secret +{{- end }} + - -p + - feature=+http2 + - -s + - malloc,{{ .Values.memorySize }} + - -n + - /tmp/varnish_workdir + volumeMounts: + - name: varnish-config + mountPath: /etc/varnish/default.vcl + subPath: default.vcl +{{- if .Values.admin.enabled }} + - name: varnish-secret + mountPath: /etc/varnish/secret + subPath: secret +{{- end }} +{{- if .Values.volumeMounts }} +{{ toYaml .Values.volumeMounts | indent 12 }} +{{- end }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP +{{- if .Values.admin.enabled }} + - name: tcp-admin + containerPort: {{ .Values.admin.port }} + protocol: TCP +{{- end }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.varnishd.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: varnish-config + configMap: + name: "{{ include "varnish.fullname" . }}" +{{- if .Values.volumes }} +{{ toYaml .Values.volumes | indent 6 }} +{{- end }} +{{- if .Values.admin.enabled }} + - name: varnish-secret + secret: + secretName: {{ include "varnish.fullname" . }} +{{- end }} diff --git a/charts/varnish/templates/dr/varnish.yaml b/charts/varnish/templates/dr/varnish.yaml new file mode 100755 index 00000000..218cd26f --- /dev/null +++ b/charts/varnish/templates/dr/varnish.yaml @@ -0,0 +1,13 @@ +{{- if .Values.destinationRule.enabled }} +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: {{ include "varnish.fullname" . }} + labels: +{{ include "varnish.labels" . | indent 4 }} +spec: + host: "{{ template "varnish.fullname" . }}.{{ .Release.Namespace }}.svc.{{ default "cluster.local" .Values.clusterDomain }}" + trafficPolicy: + tls: + mode: "{{ default "DISABLE" .Values.destinationRule.mode }}" +{{- end }} diff --git a/charts/varnish/templates/secret/varnish.yaml b/charts/varnish/templates/secret/varnish.yaml new file mode 100644 index 00000000..d911da15 --- /dev/null +++ b/charts/varnish/templates/secret/varnish.yaml @@ -0,0 +1,15 @@ +{{- if .Values.admin.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "varnish.fullname" . }} + labels: +{{ include "varnish.labels" . | indent 4 }} +type: Opaque +data: + {{- if .Values.admin.secret }} + secret: {{ .Values.admin.secret | b64enc }} + {{- else }} + secret: {{ randAlphaNum 20 | b64enc }} + {{- end }} +{{- end }} diff --git a/charts/varnish/templates/svc/varnish-headless.yaml b/charts/varnish/templates/svc/varnish-headless.yaml new file mode 100644 index 00000000..a65b7c4e --- /dev/null +++ b/charts/varnish/templates/svc/varnish-headless.yaml @@ -0,0 +1,18 @@ +{{- if .Values.admin.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "varnish.fullname" . }}-admin + labels: +{{ include "varnish.labels" . | indent 4 }} +spec: + type: ClusterIP + clusterIP: None + ports: + - name: tcp-admin + port: {{ .Values.admin.port }} + protocol: TCP + selector: + app.kubernetes.io/name: {{ include "varnish.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} diff --git a/charts/varnish/templates/svc/varnish.yaml b/charts/varnish/templates/svc/varnish.yaml new file mode 100644 index 00000000..a2b2ad00 --- /dev/null +++ b/charts/varnish/templates/svc/varnish.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "varnish.fullname" . }} + labels: +{{ include "varnish.labels" . | indent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - name: http + port: {{ .Values.service.port }} + protocol: TCP + selector: + app.kubernetes.io/name: {{ include "varnish.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} diff --git a/charts/varnish/values.yaml b/charts/varnish/values.yaml new file mode 100644 index 00000000..6b0b4152 --- /dev/null +++ b/charts/varnish/values.yaml @@ -0,0 +1,86 @@ +# Default values for varnish. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +varnishd: + ## Varnish image version + ## ref: https://hub.docker.com/_/varnish?tab=tags + ## + image: varnish + + ## Note that by default we use appVersion to get image tag + # tag: 6.4.0 + + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod + ## + # imagePullSecrets: + # - name: myRegistryKeySecretName + + ## Specify a imagePullPolicy + ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images + ## + imagePullPolicy: IfNotPresent + +nameOverride: "" +fullnameOverride: "" + +# annotations: {} + +destinationRule: + enabled: false + mode: DISABLE + +# Varnish port +service: + type: ClusterIP + port: 80 + +# The size of the Varnish memory +# (e.g., 100M, 1G) +memorySize: 100M + +# Admin +admin: + enable: false + port: 6082 + + # Set admin secret + # (when unset, a random value is generated and should be copied from the secret into your values) + # secret: replaceme + +# Use this property to override the default content with +# the --set-file option: helm install --set-file varnishConfigContent=varnish.vcl +# varnishConfigContent: + +# volumes: +# - name: example-cron-disk +# azureFile: +# shareName: '' +# secretName: '' + +# volumeMounts: +# - name: example-cron-disk +# mountPath: /path/to/folder +# readOnly: true + +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 + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/drupal/Chart.lock b/drupal/Chart.lock deleted file mode 100644 index 146a3f38..00000000 --- a/drupal/Chart.lock +++ /dev/null @@ -1,15 +0,0 @@ -dependencies: -- name: mysql - repository: https://charts.bitnami.com/bitnami - version: 9.1.7 -- name: postgresql - repository: https://charts.bitnami.com/bitnami - version: 11.6.6 -- name: redis - repository: https://charts.bitnami.com/bitnami - version: 16.13.2 -- name: varnish - repository: https://statcan.github.io/charts - version: 0.2.2 -digest: sha256:eff9b22832514728f66d261ff5cac8a31b399b52171bf06c821fdf5fca3f7fb3 -generated: "2023-01-16T08:09:32.964366-05:00" diff --git a/drupal/charts/varnish-0.2.2.tgz b/drupal/charts/varnish-0.2.2.tgz deleted file mode 100644 index b541c5b2c63e91e2617efeb6c2976ab904d7b66a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3538 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 'databasename', -* 'username' => 'sqlusername', -* 'password' => 'sqlpassword', -* 'host' => 'localhost', -* 'port' => '3306', -* 'driver' => 'mysql', -* 'prefix' => '', -* 'collation' => 'utf8mb4_general_ci', -* ); -* @endcode -*/ - -{{- if .Values.external.enabled }} -$databases['default']['default'] = array ( - 'database' => {{ .Values.external.database | quote }}, - 'username' => {{ .Values.external.user | quote }}, - 'password' => getenv('EXTERNAL_PASSWORD') ?: '', - {{- if .Values.proxysql.enabled }} - 'host' => '127.0.0.1', - {{- else if .Values.postgresql.enabled }} - 'host' => 'localhost', - {{- else }} - 'host' => {{ .Values.external.host | quote }}, - {{- end }} - 'port' => {{ .Values.external.port }}, - 'prefix' => '', - 'namespace' => 'Drupal\Core\Database\Driver\{{ .Values.external.driver }}', - 'driver' => '{{ .Values.external.driver }}', - {{- if .Values.external.initCommands }} - 'init_commands' => array ( - {{- range .Values.external.initCommands }} - {{- range $key, $value := . }} - '{{ $key }}' => {{ $value | quote }}, - {{- end }} - {{- end }} - ), - {{- end }} - {{- if .Values.external.pdo }} - 'pdo' => array ( - {{- range .Values.external.pdo }} - {{- range $key, $value := . }} - {{ $key }} => {{ $value | quote }}, - {{- end }} - {{- end }} - ), - {{- end }} -); -{{- else if .Values.mysql.enabled }} -$databases['default']['default'] = array ( - 'database' => {{ .Values.mysql.auth.database | quote }}, - 'username' => {{ .Values.mysql.auth.username | quote }}, - 'password' => getenv('MYSQL_PASSWORD') ?: '', - {{- if .Values.proxysql.enabled }} - 'host' => '127.0.0.1', - {{- else }} - 'host' => '{{ .Release.Name }}-mysql', - {{- end }} - 'port' => {{ .Values.mysql.primary.service.ports.mysql | quote }}, - 'prefix' => '', - 'namespace' => 'Drupal\Core\Database\Driver\mysql', - 'driver' => 'mysql', -); -{{- else if .Values.postgresql.enabled }} -$databases['default']['default'] = array ( - 'database' => {{ .Values.postgresql.auth.database | quote }}, - 'username' => {{ .Values.postgresql.auth.username | quote }}, - 'password' => getenv('POSTGRES_PASSWORD') ?: '', - {{- if .Values.pgbouncer.enabled }} - 'host' => 'localhost', - {{- else }} - 'host' => '{{ .Release.Name }}-postgresql', - {{- end }} - 'port' => {{ .Values.postgresql.primary.service.ports.postgresql | quote }}, - 'prefix' => '', - 'namespace' => 'Drupal\Core\Database\Driver\pgsql', - 'driver' => 'pgsql', -); -{{- end }} - -/** -* Customizing database settings. -* -* Many of the values of the $databases array can be customized for your -* particular database system. Refer to the sample in the section above as a -* starting point. -* -* The "driver" property indicates what Drupal database driver the -* connection should use. This is usually the same as the name of the -* database type, such as mysql or sqlite, but not always. The other -* properties will vary depending on the driver. For SQLite, you must -* specify a database file name in a directory that is writable by the -* webserver. For most other drivers, you must specify a -* username, password, host, and database name. -* -* Transaction support is enabled by default for all drivers that support it, -* including MySQL. To explicitly disable it, set the 'transactions' key to -* FALSE. -* Note that some configurations of MySQL, such as the MyISAM engine, don't -* support it and will proceed silently even if enabled. If you experience -* transaction related crashes with such configuration, set the 'transactions' -* key to FALSE. -* -* For each database, you may optionally specify multiple "target" databases. -* A target database allows Drupal to try to send certain queries to a -* different database if it can but fall back to the default connection if not. -* That is useful for primary/replica replication, as Drupal may try to connect -* to a replica server when appropriate and if one is not available will simply -* fall back to the single primary server (The terms primary/replica are -* traditionally referred to as master/slave in database server documentation). -* -* The general format for the $databases array is as follows: -* @code -* $databases['default']['default'] = $info_array; -* $databases['default']['replica'][] = $info_array; -* $databases['default']['replica'][] = $info_array; -* $databases['extra']['default'] = $info_array; -* @endcode -* -* In the above example, $info_array is an array of settings described above. -* The first line sets a "default" database that has one primary database -* (the second level default). The second and third lines create an array -* of potential replica databases. Drupal will select one at random for a given -* request as needed. The fourth line creates a new database with a name of -* "extra". -* -* You can optionally set prefixes for some or all database table names -* by using the 'prefix' setting. If a prefix is specified, the table -* name will be prepended with its value. Be sure to use valid database -* characters only, usually alphanumeric and underscore. If no prefixes -* are desired, leave it as an empty string ''. -* -* To have all database names prefixed, set 'prefix' as a string: -* @code -* 'prefix' => 'main_', -* @endcode -* To provide prefixes for specific tables, set 'prefix' as an array. -* The array's keys are the table names and the values are the prefixes. -* The 'default' element is mandatory and holds the prefix for any tables -* not specified elsewhere in the array. Example: -* @code -* 'prefix' => array( -* 'default' => 'main_', -* 'users' => 'shared_', -* 'sessions' => 'shared_', -* 'role' => 'shared_', -* 'authmap' => 'shared_', -* ), -* @endcode -* You can also use a reference to a schema/database as a prefix. This may be -* useful if your Drupal installation exists in a schema that is not the default -* or you want to access several databases from the same code base at the same -* time. -* Example: -* @code -* 'prefix' => array( -* 'default' => 'main.', -* 'users' => 'shared.', -* 'sessions' => 'shared.', -* 'role' => 'shared.', -* 'authmap' => 'shared.', -* ); -* @endcode -* NOTE: MySQL and SQLite's definition of a schema is a database. -* -* Advanced users can add or override initial commands to execute when -* connecting to the database server, as well as PDO connection settings. For -* example, to enable MySQL SELECT queries to exceed the max_join_size system -* variable, and to reduce the database connection timeout to 5 seconds: -* @code -* $databases['default']['default'] = array( -* 'init_commands' => array( -* 'big_selects' => 'SET SQL_BIG_SELECTS=1', -* ), -* 'pdo' => array( -* PDO::ATTR_TIMEOUT => 5, -* ), -* ); -* @endcode -* -* WARNING: The above defaults are designed for database portability. Changing -* them may cause unexpected behavior, including potential data loss. See -* https://www.drupal.org/developing/api/database/configuration for more -* information on these defaults and the potential issues. -* -* More details can be found in the constructor methods for each driver: -* - \Drupal\Core\Database\Driver\mysql\Connection::__construct() -* - \Drupal\Core\Database\Driver\pgsql\Connection::__construct() -* - \Drupal\Core\Database\Driver\sqlite\Connection::__construct() -* -* Sample Database configuration format for PostgreSQL (pgsql): -* @code -* $databases['default']['default'] = array( -* 'driver' => 'pgsql', -* 'database' => 'databasename', -* 'username' => 'sqlusername', -* 'password' => 'sqlpassword', -* 'host' => 'localhost', -* 'prefix' => '', -* ); -* @endcode -* -* Sample Database configuration format for SQLite (sqlite): -* @code -* $databases['default']['default'] = array( -* 'driver' => 'sqlite', -* 'database' => '/path/to/databasefilename', -* ); -* @endcode -*/ - -/** -* Location of the site configuration files. -* -* The $config_directories array specifies the location of file system -* directories used for configuration data. On install, the "sync" directory is -* created. This is used for configuration imports. The "active" directory is -* not created by default since the default storage for active configuration is -* the database rather than the file system. (This can be changed. See "Active -* configuration settings" below). -* -* The default location for the "sync" directory is inside a randomly-named -* directory in the public files path. The setting below allows you to override -* the "sync" location. -* -* If you use files for the "active" configuration, you can tell the -* Configuration system where this directory is located by adding an entry with -* array key CONFIG_ACTIVE_DIRECTORY. -* -* Example: -* @code -* $config_directories = array( -* CONFIG_SYNC_DIRECTORY => '/directory/outside/webroot', -* ); -* @endcode -*/ -$config_directories = array(); - -/** -* Settings: -* -* $settings contains environment-specific configuration, such as the files -* directory and reverse proxy address, and temporary configuration, such as -* security overrides. -* -* @see \Drupal\Core\Site\Settings::get() -*/ - -/** -* The active installation profile. -* -* Changing this after installation is not recommended as it changes which -* directories are scanned during extension discovery. If this is set prior to -* installation this value will be rewritten according to the profile selected -* by the user. -* -* @see install_select_profile() -*/ -# $settings['install_profile'] = ''; - -/** -* Salt for one-time login links, cancel links, form tokens, etc. -* -* This variable will be set to a random value by the installer. All one-time -* login links will be invalidated if the value is changed. Note that if your -* site is deployed on a cluster of web servers, you must ensure that this -* variable has the same value on each server. -* -* For enhanced security, you may set this variable to the contents of a file -* outside your document root; you should also ensure that this file is not -* stored with backups of your database. -* -* Example: -* @code -* $settings['hash_salt'] = file_get_contents('/home/example/salt.txt'); -* @endcode -*/ -$settings['hash_salt'] = 'default'; - -/** -* Deployment identifier. -* -* Drupal's dependency injection container will be automatically invalidated and -* rebuilt when the Drupal core version changes. When updating contributed or -* custom code that changes the container, changing this identifier will also -* allow the container to be invalidated as soon as code is deployed. -*/ -# $settings['deployment_identifier'] = \Drupal::VERSION; - -/** -* Access control for update.php script. -* -* If you are updating your Drupal installation using the update.php script but -* are not logged in using either an account with the "Administer software -* updates" permission or the site maintenance account (the account that was -* created during installation), you will need to modify the access check -* statement below. Change the FALSE to a TRUE to disable the access check. -* After finishing the upgrade, be sure to open this file again and change the -* TRUE back to a FALSE! -*/ -$settings['update_free_access'] = FALSE; - -/** -* External access proxy settings: -* -* If your site must access the Internet via a web proxy then you can enter the -* proxy settings here. Set the full URL of the proxy, including the port, in -* variables: -* - $settings['http_client_config']['proxy']['http']: The proxy URL for HTTP -* requests. -* - $settings['http_client_config']['proxy']['https']: The proxy URL for HTTPS -* requests. -* You can pass in the user name and password for basic authentication in the -* URLs in these settings. -* -* You can also define an array of host names that can be accessed directly, -* bypassing the proxy, in $settings['http_client_config']['proxy']['no']. -* -* If these settings are not configured, the system environment variables -* HTTP_PROXY, HTTPS_PROXY, and NO_PROXY on the web server will be used instead. -*/ -# $settings['http_client_config']['proxy']['http'] = 'http://proxy_user:proxy_pass@example.com:8080'; -# $settings['http_client_config']['proxy']['https'] = 'http://proxy_user:proxy_pass@example.com:8080'; -# $settings['http_client_config']['proxy']['no'] = ['127.0.0.1', 'localhost']; - -/** -* Reverse Proxy Configuration: -* -* Reverse proxy servers are often used to enhance the performance -* of heavily visited sites and may also provide other site caching, -* security, or encryption benefits. In an environment where Drupal -* is behind a reverse proxy, the real IP address of the client should -* be determined such that the correct client IP address is available -* to Drupal's logging, statistics, and access management systems. In -* the most simple scenario, the proxy server will add an -* X-Forwarded-For header to the request that contains the client IP -* address. However, HTTP headers are vulnerable to spoofing, where a -* malicious client could bypass restrictions by setting the -* X-Forwarded-For header directly. Therefore, Drupal's proxy -* configuration requires the IP addresses of all remote proxies to be -* specified in $settings['reverse_proxy_addresses'] to work correctly. -* -* Enable this setting to get Drupal to determine the client IP from -* the X-Forwarded-For header (or $settings['reverse_proxy_header'] if set). -* If you are unsure about this setting, do not have a reverse proxy, -* or Drupal operates in a shared hosting environment, this setting -* should remain commented out. -* -* In order for this setting to be used you must specify every possible -* reverse proxy IP address in $settings['reverse_proxy_addresses']. -* If a complete list of reverse proxies is not available in your -* environment (for example, if you use a CDN) you may set the -* $_SERVER['REMOTE_ADDR'] variable directly in settings.php. -* Be aware, however, that it is likely that this would allow IP -* address spoofing unless more advanced precautions are taken. -*/ -$settings['reverse_proxy'] = TRUE; - -/** -* Specify every reverse proxy IP address in your environment. -* This setting is required if $settings['reverse_proxy'] is TRUE. -*/ -$settings['reverse_proxy_addresses'] = array('0.0.0.0/0'); - -/** -* Set this value if your proxy server sends the client IP in a header -* other than X-Forwarded-For. -*/ -# $settings['reverse_proxy_header'] = 'X_CLUSTER_CLIENT_IP'; - -/** -* Set this value if your proxy server sends the client protocol in a header -* other than X-Forwarded-Proto. -*/ -# $settings['reverse_proxy_proto_header'] = 'X_FORWARDED_PROTO'; - -/** -* Set this value if your proxy server sends the client protocol in a header -* other than X-Forwarded-Host. -*/ -# $settings['reverse_proxy_host_header'] = 'X_FORWARDED_HOST'; - -/** -* Set this value if your proxy server sends the client protocol in a header -* other than X-Forwarded-Port. -*/ -# $settings['reverse_proxy_port_header'] = 'X_FORWARDED_PORT'; - -/** -* Set this value if your proxy server sends the client protocol in a header -* other than Forwarded. -*/ -# $settings['reverse_proxy_forwarded_header'] = 'FORWARDED'; - -/** -* Page caching: -* -* By default, Drupal sends a "Vary: Cookie" HTTP header for anonymous page -* views. This tells a HTTP proxy that it may return a page from its local -* cache without contacting the web server, if the user sends the same Cookie -* header as the user who originally requested the cached page. Without "Vary: -* Cookie", authenticated users would also be served the anonymous page from -* the cache. If the site has mostly anonymous users except a few known -* editors/administrators, the Vary header can be omitted. This allows for -* better caching in HTTP proxies (including reverse proxies), i.e. even if -* clients send different cookies, they still get content served from the cache. -* However, authenticated users should access the site directly (i.e. not use an -* HTTP proxy, and bypass the reverse proxy if one is used) in order to avoid -* getting cached pages from the proxy. -*/ -# $settings['omit_vary_cookie'] = TRUE; - -/** -* Class Loader. -* -* If the APC extension is detected, the Symfony APC class loader is used for -* performance reasons. Detection can be prevented by setting -* class_loader_auto_detect to false, as in the example below. -*/ -# $settings['class_loader_auto_detect'] = FALSE; - -/* -* If the APC extension is not detected, either because APC is missing or -* because auto-detection has been disabled, auto-loading falls back to -* Composer's ClassLoader, which is good for development as it does not break -* when code is moved in the file system. You can also decorate the base class -* loader with another cached solution than the Symfony APC class loader, as -* all production sites should have a cached class loader of some sort enabled. -* -* To do so, you may decorate and replace the local $class_loader variable. For -* example, to use Symfony's APC class loader without automatic detection, -* uncomment the code below. -*/ -/* -if ($settings['hash_salt']) { - $prefix = 'drupal.' . hash('sha256', 'drupal.' . $settings['hash_salt']); - $apc_loader = new \Symfony\Component\ClassLoader\ApcClassLoader($prefix, $class_loader); - unset($prefix); - $class_loader->unregister(); - $apc_loader->register(); - $class_loader = $apc_loader; -} -*/ - -/** -* Authorized file system operations: -* -* The Update Manager module included with Drupal provides a mechanism for -* site administrators to securely install missing updates for the site -* directly through the web user interface. On securely-configured servers, -* the Update manager will require the administrator to provide SSH or FTP -* credentials before allowing the installation to proceed; this allows the -* site to update the new files as the user who owns all the Drupal files, -* instead of as the user the webserver is running as. On servers where the -* webserver user is itself the owner of the Drupal files, the administrator -* will not be prompted for SSH or FTP credentials (note that these server -* setups are common on shared hosting, but are inherently insecure). -* -* Some sites might wish to disable the above functionality, and only update -* the code directly via SSH or FTP themselves. This setting completely -* disables all functionality related to these authorized file operations. -* -* @see https://www.drupal.org/node/244924 -* -* Remove the leading hash signs to disable. -*/ -# $settings['allow_authorize_operations'] = FALSE; - -/** -* Default mode for directories and files written by Drupal. -* -* Value should be in PHP Octal Notation, with leading zero. -*/ -# $settings['file_chmod_directory'] = 0775; -# $settings['file_chmod_file'] = 0664; - -/** -* Public file base URL: -* -* An alternative base URL to be used for serving public files. This must -* include any leading directory path. -* -* A different value from the domain used by Drupal to be used for accessing -* public files. This can be used for a simple CDN integration, or to improve -* security by serving user-uploaded files from a different domain or subdomain -* pointing to the same server. Do not include a trailing slash. -*/ -# $settings['file_public_base_url'] = 'http://downloads.example.com/files'; - -/** -* Public file path: -* -* A local file system path where public files will be stored. This directory -* must exist and be writable by Drupal. This directory must be relative to -* the Drupal installation directory and be accessible over the web. -*/ -# $settings['file_public_path'] = 'sites/default/files'; - -/** -* Private file path: -* -* A local file system path where private files will be stored. This directory -* must be absolute, outside of the Drupal installation directory and not -* accessible over the web. -* -* Note: Caches need to be cleared when this value is changed to make the -* private:// stream wrapper available to the system. -* -* See https://www.drupal.org/documentation/modules/file for more information -* about securing private files. -*/ -$settings['file_private_path'] = '/private'; - -/** -* Session write interval: -* -* Set the minimum interval between each session write to database. -* For performance reasons it defaults to 180. -*/ -# $settings['session_write_interval'] = 180; - -/** -* String overrides: -* -* To override specific strings on your site with or without enabling the Locale -* module, add an entry to this list. This functionality allows you to change -* a small number of your site's default English language interface strings. -* -* Remove the leading hash signs to enable. -* -* The "en" part of the variable name, is dynamic and can be any langcode of -* any added language. (eg locale_custom_strings_de for german). -*/ -# $settings['locale_custom_strings_en'][''] = array( -# 'forum' => 'Discussion board', -# '@count min' => '@count minutes', -# ); - -/** -* A custom theme for the offline page: -* -* This applies when the site is explicitly set to maintenance mode through the -* administration page or when the database is inactive due to an error. -* The template file should also be copied into the theme. It is located inside -* 'core/modules/system/templates/maintenance-page.html.twig'. -* -* Note: This setting does not apply to installation and update pages. -*/ -# $settings['maintenance_theme'] = 'bartik'; - -/** -* PHP settings: -* -* To see what PHP settings are possible, including whether they can be set at -* runtime (by using ini_set()), read the PHP documentation: -* http://php.net/manual/ini.list.php -* See \Drupal\Core\DrupalKernel::bootEnvironment() for required runtime -* settings and the .htaccess file for non-runtime settings. -* Settings defined there should not be duplicated here so as to avoid conflict -* issues. -*/ - -/** -* If you encounter a situation where users post a large amount of text, and -* the result is stripped out upon viewing but can still be edited, Drupal's -* output filter may not have sufficient memory to process it. If you -* experience this issue, you may wish to uncomment the following two lines -* and increase the limits of these variables. For more information, see -* http://php.net/manual/pcre.configuration.php. -*/ -# ini_set('pcre.backtrack_limit', 200000); -# ini_set('pcre.recursion_limit', 200000); - -/** -* Active configuration settings. -* -* By default, the active configuration is stored in the database in the -* {config} table. To use a different storage mechanism for the active -* configuration, do the following prior to installing: -* - Create an "active" directory and declare its path in $config_directories -* as explained under the 'Location of the site configuration files' section -* above in this file. To enhance security, you can declare a path that is -* outside your document root. -* - Override the 'bootstrap_config_storage' setting here. It must be set to a -* callable that returns an object that implements -* \Drupal\Core\Config\StorageInterface. -* - Override the service definition 'config.storage.active'. Put this -* override in a services.yml file in the same directory as settings.php -* (definitions in this file will override service definition defaults). -*/ -# $settings['bootstrap_config_storage'] = array('Drupal\Core\Config\BootstrapConfigStorageFactory', 'getFileStorage'); - -/** -* Configuration overrides. -* -* To globally override specific configuration values for this site, -* set them here. You usually don't need to use this feature. This is -* useful in a configuration file for a vhost or directory, rather than -* the default settings.php. -* -* Note that any values you provide in these variable overrides will not be -* viewable from the Drupal administration interface. The administration -* interface displays the values stored in configuration so that you can stage -* changes to other environments that don't have the overrides. -* -* There are particular configuration values that are risky to override. For -* example, overriding the list of installed modules in 'core.extension' is not -* supported as module install or uninstall has not occurred. Other examples -* include field storage configuration, because it has effects on database -* structure, and 'core.menu.static_menu_link_overrides' since this is cached in -* a way that is not config override aware. Also, note that changing -* configuration values in settings.php will not fire any of the configuration -* change events. -*/ -# $config['system.site']['name'] = 'My Drupal site'; -# $config['system.theme']['default'] = 'stark'; -# $config['user.settings']['anonymous'] = 'Visitor'; - -/** -* Fast 404 pages: -* -* Drupal can generate fully themed 404 pages. However, some of these responses -* are for images or other resource files that are not displayed to the user. -* This can waste bandwidth, and also generate server load. -* -* The options below return a simple, fast 404 page for URLs matching a -* specific pattern: -* - $config['system.performance']['fast_404']['exclude_paths']: A regular -* expression to match paths to exclude, such as images generated by image -* styles, or dynamically-resized images. The default pattern provided below -* also excludes the private file system. If you need to add more paths, you -* can add '|path' to the expression. -* - $config['system.performance']['fast_404']['paths']: A regular expression to -* match paths that should return a simple 404 page, rather than the fully -* themed 404 page. If you don't have any aliases ending in htm or html you -* can add '|s?html?' to the expression. -* - $config['system.performance']['fast_404']['html']: The html to return for -* simple 404 pages. -* -* Remove the leading hash signs if you would like to alter this functionality. -*/ -# $config['system.performance']['fast_404']['exclude_paths'] = '/\/(?:styles)|(?:system\/files)\//'; -# $config['system.performance']['fast_404']['paths'] = '/\.(?:txt|png|gif|jpe?g|css|js|ico|swf|flv|cgi|bat|pl|dll|exe|asp)$/i'; -# $config['system.performance']['fast_404']['html'] = '404 Not Found

Not Found

The requested URL "@path" was not found on this server.

'; - -/** -* Load services definition file. -*/ -$settings['container_yamls'][] = __DIR__ . '/services.yml'; - -/** -* Override the default service container class. -* -* This is useful for example to trace the service container for performance -* tracking purposes, for testing a service container with an error condition or -* to test a service container that throws an exception. -*/ -# $settings['container_base_class'] = '\Drupal\Core\DependencyInjection\Container'; - -/** -* Trusted host configuration. -* -* Drupal core can use the Symfony trusted host mechanism to prevent HTTP Host -* header spoofing. -* -* To enable the trusted host mechanism, you enable your allowable hosts -* in $settings['trusted_host_patterns']. This should be an array of regular -* expression patterns, without delimiters, representing the hosts you would -* like to allow. -* -* For example: -* @code -* $settings['trusted_host_patterns'] = array( -* '^www\.example\.com$', -* ); -* @endcode -* will allow the site to only run from www.example.com. -* -* If you are running multisite, or if you are running your site from -* different domain names (eg, you don't redirect http://www.example.com to -* http://example.com), you should specify all of the host patterns that are -* allowed by your site. -* -* For example: -* @code -* $settings['trusted_host_patterns'] = array( -* '^example\.com$', -* '^.+\.example\.com$', -* '^example\.org$', -* '^.+\.example\.org$', -* ); -* @endcode -* will allow the site to run off of all variants of example.com and -* example.org, with all subdomains included. -*/ - -/** -* Get environment settings. -* -* Production (default): normal production settings. -* Development: Use development settings. -*/ -$drupal_settings = 'production'; -if (isset($_ENV['DRUPAL_SETTINGS'])) { - $drupal_settings = $_ENV['DRUPAL_SETTINGS']; -} - -/** Todo: create better patterns on production sites */ -if ($drupal_settings !== 'production') { - $settings['trusted_host_patterns'] = array('[\s\S]*'); -} - -/** -* Load local development override configuration, if available. -* -* Use settings.local.php to override variables on secondary (staging, -* development, etc) installations of this site. Typically used to disable -* caching, JavaScript/CSS compression, re-routing of outgoing emails, and -* other things that should not happen on development and testing sites. -* -* Keep this code block at the end of this file to take full effect. -*/ -if ($drupal_settings === 'development' && file_exists(__DIR__ . '/settings.local.php')) { - include __DIR__ . '/settings.local.php'; -} - -/** Everything after here is added by the installation process. -* -* TODO: improve the installation by putting the settings.local part below these -* settings. -*/ - -$config_directories[CONFIG_SYNC_DIRECTORY] = '{{ .Values.drupal.configSync.directory }}'; - -{{- if .Values.drupal.configSplit.enabled }} -/** - * Configuration Split for Configuration Management - * - * WxT is following the best practices given by Acquia for configuration - * management. The "default" configuration directory should be shared between - * all multi-sites, and each multisite will override this selectively using - * configuration splits. - * - * To disable this functionality simply set the following parameters: - * $wxt_override_config_dirs = FALSE; - * $settings['config_sync_directory'] = $dir . "/private/config/$site_dir"; - * - * See https://github.com/acquia/blt/blob/12.x/settings/config.settings.php - * for more information. - */ - -use Drupal\wxt\Robo\Common\EnvironmentDetector; - -if (!isset($wxt_override_config_dirs)) { - $wxt_override_config_dirs = TRUE; -} -if ($wxt_override_config_dirs) { - $config_directories['sync'] = $repo_root . "/private/config/default"; - $settings['config_sync_directory'] = $repo_root . "/private/config/default"; -} -$split_filename_prefix = 'config_split.config_split'; -if (isset($config_directories['sync'])) { - $split_filepath_prefix = $config_directories['sync'] . '/' . $split_filename_prefix; -} -else { - $split_filepath_prefix = $settings['config_sync_directory'] . '/' . $split_filename_prefix; -} - -/** - * Set environment splits. - */ -$split_envs = [ - 'local', - 'dev', - 'test', - 'qa', - 'prod', - 'ci', -]; -foreach ($split_envs as $split_env) { - $config["$split_filename_prefix.$split_env"]['status'] = FALSE; -} -if (!isset($split)) { - $split = 'none'; - if (EnvironmentDetector::isLocalEnv()) { - $split = 'local'; - } - if (EnvironmentDetector::isCiEnv()) { - $split = 'ci'; - } - if (EnvironmentDetector::isDevEnv()) { - $split = 'dev'; - } - elseif (EnvironmentDetector::isTestEnv()) { - $split = 'test'; - } - elseif (EnvironmentDetector::isQaEnv()) { - $split = 'qa'; - } - elseif (EnvironmentDetector::isProdEnv()) { - $split = 'prod'; - } -} -if ($split != 'none') { - $config["$split_filename_prefix.$split"]['status'] = TRUE; -} - -/** - * Set multisite split. - */ -// $config["$split_filename_prefix.SITENAME"]['status'] = TRUE; -{{- end }} - -{{- if .Values.redis.enabled }} -if (extension_loaded('redis')) { - // Set Redis as the default backend for any cache bin not otherwise specified. - $settings['cache']['default'] = 'cache.backend.redis'; - $settings['redis.connection']['interface'] = '{{ default "PhpRedis" .Values.redis.clientInterface }}'; - $settings['redis.connection']['scheme'] = 'http'; - {{- if .Values.redis.sentinel.enabled }} - $settings['redis.connection']['host'] = ['{{ .Release.Name }}-redis:{{ .Values.redis.sentinel.service.sentinelPort }}']; - $settings['redis.connection']['instance'] = '{{ .Values.redis.sentinel.masterSet }}'; - {{- else }} - $settings['redis.connection']['host'] = '{{ .Release.Name }}-redis-master'; - $settings['redis.connection']['port'] = '{{ .Values.redis.master.service.ports.redis }}'; - {{- end }} - $settings['redis.connection']['password'] = getenv('REDIS_PASSWORD') ?: ''; - $settings['redis.connection']['persistent'] = FALSE; - - // Allow the services to work before the Redis module itself is enabled. - $settings['container_yamls'][] = 'modules/contrib/redis/example.services.yml'; - $settings['container_yamls'][] = 'modules/contrib/redis/redis.services.yml'; - - // Manually add the classloader path, this is required for the container cache bin definition below - // and allows to use it without the redis module being enabled. - $class_loader->addPsr4('Drupal\\redis\\', 'modules/contrib/redis/src'); - - $settings['bootstrap_container_definition'] = [ - 'parameters' => [], - 'services' => [ - 'redis.factory' => [ - 'class' => 'Drupal\redis\ClientFactory', - ], - 'cache.backend.redis' => [ - 'class' => 'Drupal\redis\Cache\CacheBackendFactory', - 'arguments' => ['@redis.factory', '@cache_tags_provider.container', '@serialization.phpserialize'], - ], - 'cache.container' => [ - 'class' => '\Drupal\redis\Cache\PhpRedis', - 'factory' => ['@cache.backend.redis', 'get'], - 'arguments' => ['container'], - ], - 'cache_tags_provider.container' => [ - 'class' => 'Drupal\redis\Cache\RedisCacheTagsChecksum', - 'arguments' => ['@redis.factory'], - ], - 'serialization.phpserialize' => [ - 'class' => 'Drupal\Component\Serialization\PhpSerialize', - ], - ], - ]; - - /** Optional prefix for cache entries */ - $settings['cache_prefix'] = 'drupal_'; - - // Always set the fast backend for bootstrap, discover and config, otherwise - // this gets lost when redis is enabled. - $settings['cache']['bins']['bootstrap'] = 'cache.backend.chainedfast'; - $settings['cache']['bins']['discovery'] = 'cache.backend.chainedfast'; - $settings['cache']['bins']['config'] = 'cache.backend.chainedfast'; - - // Use for all bins otherwise specified. - $settings['cache']['default'] = 'cache.backend.redis'; - - // Use for all queues unless otherwise specified for a specific queue. - $settings['queue_default'] = 'queue.redis'; - - // Or if you want to use reliable queue implementation. - // $settings['queue_default'] = 'queue.redis_reliable'; - - // Use this to only use Redis for a specific queue. - // $settings['queue_service_aggregator_feeds'] = 'queue.redis'; - - // Use this to use reliable queue implementation. - // $settings['queue_service_aggregator_feeds'] = 'queue.redis_reliable'; -} -{{- end }} - -// As recommended in the S3FS docs, change the twig storage directory -$settings['php_storage']['twig']['directory'] = '/cache/twig'; - -if (is_file(__DIR__ . '/extra.settings.php')) { - include __DIR__ . '/extra.settings.php'; -} diff --git a/drupal/conf/varnish.yaml b/drupal/conf/varnish.yaml deleted file mode 100644 index e69de29b..00000000 diff --git a/drupal/conf/www.conf b/drupal/conf/www.conf deleted file mode 100644 index 30ffa113..00000000 --- a/drupal/conf/www.conf +++ /dev/null @@ -1,9 +0,0 @@ -[www] -user = www-data -group = www-data -listen = 127.0.0.1:9000 -pm = dynamic -pm.max_children = 50 -pm.start_servers = 5 -pm.min_spare_servers = 5 -pm.max_spare_servers = 35 diff --git a/drupal/templates/cm/drupal.yaml b/drupal/templates/cm/drupal.yaml deleted file mode 100644 index 9c98ae0a..00000000 --- a/drupal/templates/cm/drupal.yaml +++ /dev/null @@ -1,41 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "drupal.fullname" . }} - labels: - app.kubernetes.io/name: {{ include "drupal.name" . }} - helm.sh/chart: {{ include "drupal.chart" . }} - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/managed-by: {{ .Release.Service }} -data: - php.ini: | -{{ tpl (.Files.Get "conf/php.ini") . | indent 4 }} - opcache-recommended.ini: | -{{ tpl (.Files.Get "conf/opcache-recommended.ini") . | indent 4 }} - www.conf: | -{{ tpl (.Files.Get "conf/www.conf") . | indent 4 }} - settings.php: | -{{- if eq "d8" .Values.drupal.version }} -{{ tpl (.Files.Get "conf/settings.d8.php") . | indent 4 }} -{{- else if eq "d9" .Values.drupal.version }} -{{ tpl (.Files.Get "conf/settings.d9.php") . | indent 4 }} -{{- else }} - settings.php: - =1.21" $.Capabilities.KubeVersion.GitVersion }} -apiVersion: batch/v1 -{{- else }} -apiVersion: batch/v1beta1 -{{- end }} -kind: CronJob -metadata: - name: {{ $fullName }}-{{ $cronName }} - labels: - app.kubernetes.io/name: {{ $name }} - helm.sh/chart: {{ $chartName }} - app.kubernetes.io/instance: {{ $release.Name }} - app.kubernetes.io/managed-by: {{ $release.Service }} -spec: - schedule: "{{ $cron.schedule }}" - startingDeadlineSeconds: 100 - concurrencyPolicy: Replace - successfulJobsHistoryLimit: 5 - failedJobsHistoryLimit: 5 - jobTemplate: - spec: - template: - metadata: - labels: - app.kubernetes.io/name: {{ $name }} - helm.sh/chart: {{ $chartName }} - app.kubernetes.io/instance: {{ $release.Name }} - app.kubernetes.io/managed-by: {{ $release.Service }} - spec: -{{- if $values.drupal.tolerations }} - tolerations: -{{ toYaml $values.drupal.tolerations | indent 10 }} -{{- end }} -{{- if $values.drupal.nodeSelector }} - nodeSelector: -{{ toYaml $values.drupal.nodeSelector | indent 12 }} -{{- end }} - restartPolicy: OnFailure - containers: - - name: cron - image: "{{ $values.drupal.image }}:{{ default $chart.AppVersion $values.drupal.tag }}" - imagePullPolicy: {{ default "" $values.drupal.imagePullPolicy | quote }} - command: - - '/bin/sh' - - '-c' - - | -{{ $cron.script | indent 14 }} - env: -{{- if $values.external.enabled }} - - name: EXTERNAL_PASSWORD - valueFrom: - secretKeyRef: - name: {{ $fullName }} - key: databasePassword -{{- else if $values.mysql.enabled }} - - name: MYSQL_PASSWORD - valueFrom: - secretKeyRef: - # This is not ideal, but calling the template - # was returning the wrong result. - name: "{{ $release.Name }}-mysql" - key: mysql-password -{{- else if $values.postgresql.enabled }} - - name: POSTGRES_PASSWORD - valueFrom: - secretKeyRef: - name: "{{ $release.Name }}-postgresql" - key: password -{{- end }} -{{- if $values.redis.enabled }} - - name: REDIS_PASSWORD - valueFrom: - secretKeyRef: - name: "{{ $release.Name }}-redis" - key: redis-password -{{- end }} - - name: DRUPAL_ADMIN_PASSWORD - valueFrom: - secretKeyRef: - name: "{{ $fullName }}" - key: password -{{- if $values.extraVars }} -{{ toYaml $values.extraVars | indent 12 }} -{{- end }} - volumeMounts: - - name: cm-drupal - readOnly: true - mountPath: /usr/local/etc/php/php.ini - subPath: php.ini - - name: cm-drupal - readOnly: true - mountPath: /usr/local/etc/php/conf.d/opcache-recommended.ini - subPath: opcache-recommended.ini - - name: cm-drupal - readOnly: true - mountPath: /usr/local/etc/php-fpm.d/www.conf - subPath: www.conf - - name: cm-drupal - mountPath: /var/www/html/sites/default/settings.php - subPath: settings.php - readOnly: true - - name: cm-drupal - mountPath: /var/www/html/sites/default/extra.settings.php - subPath: extra.settings.php - readOnly: true - - name: cm-drupal - mountPath: /var/www/html/sites/default/services.yml - subPath: services.yml - readOnly: true - - name: ssmtp - mountPath: /etc/ssmtp/ssmtp.conf - subPath: ssmtp.conf - readOnly: true - - name: twig-cache - mountPath: /cache/twig -{{- if not $values.drupal.disableDefaultFilesMount }} - - name: files - mountPath: /var/www/html/sites/default/files - subPath: public - - name: files - mountPath: /private - subPath: private -{{- end }} -{{- if $values.drupal.volumeMounts }} -{{ toYaml $values.drupal.volumeMounts | indent 12 }} -{{- end }} -{{- if $cron.volumeMounts }} -{{ toYaml $cron.volumeMounts | indent 12 }} -{{- end }} -{{- if $values.proxysql.enabled }} - - name: proxysql - image: proxysql/proxysql:2.1.0 - imagePullPolicy: Always - ports: - - containerPort: 6032 - - containerPort: 6033 - volumeMounts: - - name: configfiles - mountPath: "/etc/proxysql" - readOnly: true - livenessProbe: - tcpSocket: - port: 6032 - periodSeconds: 60 - command: ["/usr/bin/proxysql", "--initial", "-f", "-c", "/etc/proxysql/proxysql.conf"] - securityContext: - allowPrivilegeEscalation: false - runAsUser: 0 - runAsGroup: 999 -{{- else if $values.pgbouncer.enabled }} - - name: pgbouncer - image: mcr.microsoft.com/azure-oss-db-tools/pgbouncer-sidecar:latest - imagePullPolicy: Always - ports: - - containerPort: 5432 - volumeMounts: - - name: configfiles - mountPath: "/etc/pgbouncer" - readOnly: true - livenessProbe: - tcpSocket: - port: 5432 - periodSeconds: 60 - lifecycle: - preStop: - exec: - command: ["/bin/sh", "-c", "killall -INT pgbouncer && sleep 120"] - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: ['all'] -{{- end }} -{{- if $values.drupal.imagePullSecrets }} - imagePullSecrets: -{{ toYaml $values.drupal.imagePullSecrets | indent 12 }} -{{- end }} - # Allow non-root user to access PersistentVolume - securityContext: -{{ toYaml $values.drupal.securityContext | indent 12 }} - volumes: - - name: cm-drupal - configMap: - name: {{ $fullName }} - - name: ssmtp - secret: - secretName: {{ $fullName }}-ssmtp - items: - - key: ssmtp.conf - path: ssmtp.conf - - name: twig-cache - emptyDir: {} -{{- if $values.drupal.persistence.enabled }} - - name: files - persistentVolumeClaim: - claimName: {{ $fullName }}-drupal -{{- else if or ($values.azure.azureFile.enabled) ($values.azure.sharedDisk.enabled) }} - - name: files-public - persistentVolumeClaim: - claimName: {{ $fullName }}-public - - name: files-private - persistentVolumeClaim: - claimName: {{ $fullName }}-private -{{- else if not $values.drupal.disableDefaultFilesMount }} - - name: files - emptyDir: {} -{{- end }} -{{- if $values.proxysql.enabled }} - - name: configfiles - secret: - secretName: {{ $fullName }}-proxysql -{{- else if $values.pgbouncer.enabled }} - - name: configfiles - secret: - secretName: {{ $fullName }}-pgbouncer -{{- end }} -{{- if $values.drupal.volumes }} -{{ toYaml $values.drupal.volumes | indent 10 }} -{{- end }} -{{- if $cron.volumes }} -{{ toYaml $cron.volumes | indent 10 }} -{{- end }} -{{- end }} -{{- end }} diff --git a/drupal/templates/cronjob/drupal-backup.yaml b/drupal/templates/cronjob/drupal-backup.yaml deleted file mode 100644 index 2ad48c29..00000000 --- a/drupal/templates/cronjob/drupal-backup.yaml +++ /dev/null @@ -1,245 +0,0 @@ -{{- if .Values.drupal.backup.enabled }} -{{- if semverCompare ">=1.21" $.Capabilities.KubeVersion.GitVersion }} -apiVersion: batch/v1 -{{- else }} -apiVersion: batch/v1beta1 -{{- end }} -kind: CronJob -metadata: - name: {{ template "drupal.fullname" . }}-drupal-backup - labels: - app.kubernetes.io/name: {{ include "drupal.name" . }} - helm.sh/chart: {{ include "drupal.chart" . }} - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/managed-by: {{ .Release.Service }} -spec: - schedule: "{{ .Values.drupal.backup.schedule }}" - startingDeadlineSeconds: 100 - concurrencyPolicy: Replace - successfulJobsHistoryLimit: 5 - failedJobsHistoryLimit: 5 - jobTemplate: - spec: - template: - metadata: - labels: - app.kubernetes.io/name: {{ include "drupal.name" . }} - helm.sh/chart: {{ include "drupal.chart" . }} - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - spec: -{{- if .Values.drupal.tolerations }} - tolerations: -{{ toYaml .Values.drupal.tolerations | indent 10 }} -{{- end }} -{{- if .Values.drupal.nodeSelector }} - nodeSelector: -{{ toYaml .Values.drupal.nodeSelector | indent 12 }} -{{- end }} - restartPolicy: OnFailure - containers: - - name: drush - image: "{{ .Values.drupal.image }}:{{ default .Chart.AppVersion .Values.drupal.tag }}" - imagePullPolicy: {{ default "" .Values.drupal.imagePullPolicy | quote }} - command: - - '/bin/sh' - - '-c' - - | - # Errors should fail the job - set -e - - # Wait for DB to be available - until drush sql:query 'SHOW TABLES;'; do echo Waiting for DB; sleep 3; done - echo DB available - - # Check Drush status - drush status - - # Run cron - BACKUPNAME=$(date +%Y%m%d.%H%M%S) - mkdir -p /backup/$BACKUPNAME - echo "Backup DB" - {{- if .Values.mysql.enabled }} - drush -y sql-dump {{ .Values.drupal.backup.sqlDumpArgs }} --extra-dump=--no-tablespaces | gzip > /backup/$BACKUPNAME/db.sql.gz - {{- else }} - drush -y sql-dump {{ .Values.drupal.backup.sqlDumpArgs }} | gzip > /backup/$BACKUPNAME/db.sql.gz - {{- end }} - echo "Backup public files" - tar {{ .Values.drupal.backup.filesArgs }} -czvf /backup/$BACKUPNAME/files.tar.gz --directory=sites/default/files . - echo "Backup private files" - tar {{ .Values.drupal.backup.privateArgs }} -czvf /backup/$BACKUPNAME/private.tar.gz --directory=/private . - env: -{{- if .Values.external.enabled }} - - name: EXTERNAL_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "drupal.fullname" . }} - key: databasePassword -{{- else if .Values.mysql.enabled }} - - name: MYSQL_PASSWORD - valueFrom: - secretKeyRef: - name: "{{ .Release.Name }}-mysql" - key: mysql-password -{{- else if .Values.postgresql.enabled }} - - name: POSTGRES_PASSWORD - valueFrom: - secretKeyRef: - name: "{{ .Release.Name }}-postgresql" - key: password -{{- end }} -{{- if .Values.redis.enabled }} - - name: REDIS_PASSWORD - valueFrom: - secretKeyRef: - name: "{{ .Release.Name }}-redis" - key: redis-password -{{- end }} - - name: DRUPAL_ADMIN_PASSWORD - valueFrom: - secretKeyRef: - name: "{{ include "drupal.fullname" . }}" - key: password -{{- if .Values.extraVars }} -{{ toYaml .Values.extraVars | indent 12 }} -{{- end }} - volumeMounts: - - name: cm-drupal - readOnly: true - mountPath: /usr/local/etc/php/php.ini - subPath: php.ini - - name: cm-drupal - readOnly: true - mountPath: /usr/local/etc/php/conf.d/opcache-recommended.ini - subPath: opcache-recommended.ini - - name: cm-drupal - readOnly: true - mountPath: /usr/local/etc/php-fpm.d/www.conf - subPath: www.conf - - name: cm-drupal - mountPath: /var/www/html/sites/default/settings.php - subPath: settings.php - readOnly: true - - name: cm-drupal - mountPath: /var/www/html/sites/default/extra.settings.php - subPath: extra.settings.php - readOnly: true - - name: cm-drupal - mountPath: /var/www/html/sites/default/services.yml - subPath: services.yml - readOnly: true - - name: ssmtp - mountPath: /etc/ssmtp/ssmtp.conf - subPath: ssmtp.conf - readOnly: true - - name: twig-cache - mountPath: /cache/twig - - name: backup - mountPath: /backup -{{- if not .Values.drupal.disableDefaultFilesMount }} - - name: files - mountPath: /var/www/html/sites/default/files - subPath: public - - name: files - mountPath: /private - subPath: private -{{- end }} -{{- if .Values.drupal.volumeMounts }} -{{ toYaml .Values.drupal.volumeMounts | indent 12 }} -{{- end }} -{{- if .Values.proxysql.enabled }} - - name: proxysql - image: proxysql/proxysql:2.1.0 - imagePullPolicy: Always - ports: - - containerPort: 6032 - - containerPort: 6033 - volumeMounts: - - name: configfiles - mountPath: "/etc/proxysql" - readOnly: true - livenessProbe: - tcpSocket: - port: 6032 - periodSeconds: 60 - command: ["/usr/bin/proxysql", "--initial", "-f", "-c", "/etc/proxysql/proxysql.conf"] - securityContext: - allowPrivilegeEscalation: false - runAsUser: 0 - runAsGroup: 999 -{{- else if .Values.pgbouncer.enabled }} - - name: pgbouncer - image: mcr.microsoft.com/azure-oss-db-tools/pgbouncer-sidecar:latest - imagePullPolicy: Always - ports: - - containerPort: 5432 - volumeMounts: - - name: configfiles - mountPath: "/etc/pgbouncer" - readOnly: true - livenessProbe: - tcpSocket: - port: 5432 - periodSeconds: 60 - lifecycle: - preStop: - exec: - command: ["/bin/sh", "-c", "killall -INT pgbouncer && sleep 120"] - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: ['all'] -{{- end }} - {{- if .Values.drupal.imagePullSecrets }} - imagePullSecrets: -{{ toYaml .Values.drupal.imagePullSecrets | indent 12 }} - {{- end }} - # Allow non-root user to access PersistentVolume - securityContext: -{{ toYaml .Values.drupal.securityContext | indent 12 }} - volumes: - - name: cm-drupal - configMap: - name: {{ include "drupal.fullname" . }} - - name: ssmtp - secret: - secretName: {{ include "drupal.fullname" . }}-ssmtp - items: - - key: ssmtp.conf - path: ssmtp.conf - - name: twig-cache - emptyDir: {} - - name: backup -{{- if .Values.drupal.backup.volume }} -{{ toYaml .Values.drupal.backup.volume | indent 12 }} -{{- else }} - emptyDir: {} -{{- end }} -{{- if .Values.drupal.persistence.enabled }} - - name: files - persistentVolumeClaim: - claimName: {{ template "drupal.fullname" . }}-drupal -{{- else if or (.Values.azure.azureFile.enabled) (.Values.azure.sharedDisk.enabled) }} - - name: files-public - persistentVolumeClaim: - claimName: {{ include "drupal.fullname" . }}-public - - name: files-private - persistentVolumeClaim: - claimName: {{ include "drupal.fullname" . }}-private -{{- else if not .Values.drupal.disableDefaultFilesMount }} - - name: files - emptyDir: {} -{{- end }} -{{- if .Values.proxysql.enabled }} - - name: configfiles - secret: - secretName: {{ include "drupal.fullname" . }}-proxysql -{{- else if .Values.pgbouncer.enabled }} - - name: configfiles - secret: - secretName: {{ include "drupal.fullname" . }}-pgbouncer -{{- end }} -{{- if .Values.drupal.volumes }} -{{ toYaml .Values.drupal.volumes | indent 10 }} -{{- end }} -{{- end }} diff --git a/drupal/templates/cronjob/drupal.yaml b/drupal/templates/cronjob/drupal.yaml deleted file mode 100644 index 6f894dba..00000000 --- a/drupal/templates/cronjob/drupal.yaml +++ /dev/null @@ -1,226 +0,0 @@ -{{- if .Values.drupal.cron.enabled }} -{{- if semverCompare ">=1.21" $.Capabilities.KubeVersion.GitVersion }} -apiVersion: batch/v1 -{{- else }} -apiVersion: batch/v1beta1 -{{- end }} -kind: CronJob -metadata: - name: {{ template "drupal.fullname" . }}-drupal-cron - labels: - app.kubernetes.io/name: {{ include "drupal.name" . }} - helm.sh/chart: {{ include "drupal.chart" . }} - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/managed-by: {{ .Release.Service }} -spec: - schedule: "{{ .Values.drupal.cron.schedule }}" - startingDeadlineSeconds: 100 - concurrencyPolicy: Replace - successfulJobsHistoryLimit: 5 - failedJobsHistoryLimit: 5 - jobTemplate: - spec: - template: - metadata: - labels: - app.kubernetes.io/name: {{ include "drupal.name" . }} - helm.sh/chart: {{ include "drupal.chart" . }} - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - spec: -{{- if .Values.drupal.tolerations }} - tolerations: -{{ toYaml .Values.drupal.tolerations | indent 10 }} -{{- end }} -{{- if .Values.drupal.nodeSelector }} - nodeSelector: -{{ toYaml .Values.drupal.nodeSelector | indent 12 }} -{{- end }} - restartPolicy: OnFailure - containers: - - name: drush - image: "{{ .Values.drupal.image }}:{{ default .Chart.AppVersion .Values.drupal.tag }}" - imagePullPolicy: {{ default "" .Values.drupal.imagePullPolicy | quote }} - command: - - '/bin/sh' - - '-c' - - | - # Errors should fail the job - set -e - - # Wait for DB to be available - until drush sql:query 'SHOW TABLES;'; do echo Waiting for DB; sleep 3; done - echo DB available - - # Check Drush status - drush status - - # Run cron - drush -y core-cron - env: -{{- if .Values.external.enabled }} - - name: EXTERNAL_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "drupal.fullname" . }} - key: databasePassword -{{- else if .Values.mysql.enabled }} - - name: MYSQL_PASSWORD - valueFrom: - secretKeyRef: - name: "{{ .Release.Name }}-mysql" - key: mysql-password -{{- else if .Values.postgresql.enabled }} - - name: POSTGRES_PASSWORD - valueFrom: - secretKeyRef: - name: "{{ .Release.Name }}-postgresql" - key: password -{{- end }} -{{- if .Values.redis.enabled }} - - name: REDIS_PASSWORD - valueFrom: - secretKeyRef: - name: "{{ .Release.Name }}-redis" - key: redis-password -{{- end }} - - name: DRUPAL_ADMIN_PASSWORD - valueFrom: - secretKeyRef: - name: "{{ include "drupal.fullname" . }}" - key: password -{{- if .Values.extraVars }} -{{ toYaml .Values.extraVars | indent 12 }} -{{- end }} - volumeMounts: - - name: cm-drupal - readOnly: true - mountPath: /usr/local/etc/php/php.ini - subPath: php.ini - - name: cm-drupal - readOnly: true - mountPath: /usr/local/etc/php/conf.d/opcache-recommended.ini - subPath: opcache-recommended.ini - - name: cm-drupal - readOnly: true - mountPath: /usr/local/etc/php-fpm.d/www.conf - subPath: www.conf - - name: cm-drupal - mountPath: /var/www/html/sites/default/settings.php - subPath: settings.php - readOnly: true - - name: cm-drupal - mountPath: /var/www/html/sites/default/extra.settings.php - subPath: extra.settings.php - readOnly: true - - name: cm-drupal - mountPath: /var/www/html/sites/default/services.yml - subPath: services.yml - readOnly: true - - name: ssmtp - mountPath: /etc/ssmtp/ssmtp.conf - subPath: ssmtp.conf - readOnly: true - - name: twig-cache - mountPath: /cache/twig -{{- if not .Values.drupal.disableDefaultFilesMount }} - - name: files - mountPath: /var/www/html/sites/default/files - subPath: public - - name: files - mountPath: /private - subPath: private -{{- end }} -{{- if .Values.drupal.volumeMounts }} -{{ toYaml .Values.drupal.volumeMounts | indent 12 }} -{{- end }} -{{- if .Values.proxysql.enabled }} - - name: proxysql - image: proxysql/proxysql:2.1.0 - imagePullPolicy: Always - ports: - - containerPort: 6032 - - containerPort: 6033 - volumeMounts: - - name: configfiles - mountPath: "/etc/proxysql" - readOnly: true - livenessProbe: - tcpSocket: - port: 6032 - periodSeconds: 60 - command: ["/usr/bin/proxysql", "--initial", "-f", "-c", "/etc/proxysql/proxysql.conf"] - securityContext: - allowPrivilegeEscalation: false - runAsUser: 0 - runAsGroup: 999 -{{- else if .Values.pgbouncer.enabled }} - - name: pgbouncer - image: mcr.microsoft.com/azure-oss-db-tools/pgbouncer-sidecar:latest - imagePullPolicy: Always - ports: - - containerPort: 5432 - volumeMounts: - - name: configfiles - mountPath: "/etc/pgbouncer" - readOnly: true - livenessProbe: - tcpSocket: - port: 5432 - periodSeconds: 60 - lifecycle: - preStop: - exec: - command: ["/bin/sh", "-c", "killall -INT pgbouncer && sleep 120"] - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: ['all'] -{{- end }} - {{- if .Values.drupal.imagePullSecrets }} - imagePullSecrets: -{{ toYaml .Values.drupal.imagePullSecrets | indent 12 }} - {{- end }} - # Allow non-root user to access PersistentVolume - securityContext: -{{ toYaml .Values.drupal.securityContext | indent 12 }} - volumes: - - name: cm-drupal - configMap: - name: {{ include "drupal.fullname" . }} - - name: ssmtp - secret: - secretName: {{ include "drupal.fullname" . }}-ssmtp - items: - - key: ssmtp.conf - path: ssmtp.conf - - name: twig-cache - emptyDir: {} -{{- if .Values.drupal.persistence.enabled }} - - name: files - persistentVolumeClaim: - claimName: {{ template "drupal.fullname" . }}-drupal -{{- else if or (.Values.azure.azureFile.enabled) (.Values.azure.sharedDisk.enabled) }} - - name: files-public - persistentVolumeClaim: - claimName: {{ include "drupal.fullname" . }}-public - - name: files-private - persistentVolumeClaim: - claimName: {{ include "drupal.fullname" . }}-private -{{- else if not .Values.drupal.disableDefaultFilesMount }} - - name: files - emptyDir: {} -{{- end }} -{{- if .Values.proxysql.enabled }} - - name: configfiles - secret: - secretName: {{ include "drupal.fullname" . }}-proxysql -{{- else if .Values.pgbouncer.enabled }} - - name: configfiles - secret: - secretName: {{ include "drupal.fullname" . }}-pgbouncer -{{- end }} -{{- if .Values.drupal.volumes }} -{{ toYaml .Values.drupal.volumes | indent 10 }} -{{- end }} -{{- end }} diff --git a/drupal/templates/deploy/drupal.yaml b/drupal/templates/deploy/drupal.yaml deleted file mode 100644 index fdc74126..00000000 --- a/drupal/templates/deploy/drupal.yaml +++ /dev/null @@ -1,292 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "drupal.fullname" . }} - labels: - app.kubernetes.io/name: {{ include "drupal.name" . }} - helm.sh/chart: {{ include "drupal.chart" . }} - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/managed-by: {{ .Release.Service }} -spec: - replicas: {{ .Values.drupal.replicas }} - strategy: - type: RollingUpdate - selector: - matchLabels: - app.kubernetes.io/name: {{ include "drupal.name" . }} - app.kubernetes.io/instance: {{ .Release.Name }} - tier: drupal - template: - metadata: - labels: - app.kubernetes.io/name: {{ include "drupal.name" . }} - app.kubernetes.io/instance: {{ .Release.Name }} - tier: drupal - annotations: -{{- if .Values.drupal.podAnnotations }} -{{ toYaml .Values.drupal.podAnnotations | indent 8 }} -{{- end }} - checksum/config: {{ include (print $.Template.BasePath "/cm/drupal.yaml") . | sha256sum }} - spec: -{{- if .Values.drupal.tolerations }} - tolerations: -{{ toYaml .Values.drupal.tolerations | indent 6 }} -{{- end }} -{{- if .Values.drupal.nodeSelector }} - nodeSelector: -{{ toYaml .Values.drupal.nodeSelector | indent 8 }} -{{- end }} -{{- if or (.Values.drupal.initContainers) (.Values.drupal.volumePermissions.enabled) (or (.Values.azure.azureFile.enabled) (.Values.azure.sharedDisk.enabled)) }} - initContainers: -{{- if .Values.drupal.volumePermissions.enabled }} - - name: set-volume-permissions - image: 'alpine:3.10' - command: - - chown - - '-R' - - '84:84' - - /files/public - - /files/private - volumeMounts: - - name: files-public - mountPath: /files/public - - name: files-private - mountPath: /files/private - securityContext: - runAsUser: 0 -{{- end }} -{{- if .Values.azure.sharedDisk.enabled }} - - name: init-chown - image: 'alpine:3.10' - command: - - chown - - '-R' - - '82:82' - - /mnt/azure - volumeMounts: - - name: files-public - mountPath: /mnt/azure -{{- end }} -{{- if or (and .Values.azure.azureFile.enabled .Values.azure.azureFile.initMediaIconsFolder) (and .Values.azure.sharedDisk.enabled .Values.azure.sharedDisk.initMediaIconsFolder) }} - - name: init-media-icons-folder - image: 'alpine:3.10' - command: - - mkdir - - '-p' - - /files/media-icons/generic - volumeMounts: - - name: files-public - mountPath: /files -{{- end }} -{{- if not (eq .Values.drupal.siteRoot "/") }} - - name: init-site-root - image: 'alpine:3.10' - command: - - /bin/sh - - '-c' - - | - mkdir -p "/webroot$(dirname "{{ .Values.drupal.siteRoot }}")" - ln -s /var/www/html "/webroot{{ .Values.drupal.siteRoot }}" - volumeMounts: - - name: webroot - mountPath: /webroot -{{- end }} -{{- if .Values.drupal.initContainers }} -{{ toYaml .Values.drupal.initContainers | indent 8 }} -{{- end }} -{{- end }} - containers: - - image: "{{ .Values.drupal.image }}:{{ default .Chart.AppVersion .Values.drupal.tag }}" - imagePullPolicy: {{ default "" .Values.drupal.imagePullPolicy | quote }} - name: drupal -{{- if .Values.drupal.healthcheck.enabled }} - livenessProbe: - exec: - command: - - php-fpm-healthcheck - initialDelaySeconds: 0 - periodSeconds: 5 - readinessProbe: - exec: - command: - - php-fpm-healthcheck - initialDelaySeconds: 1 - periodSeconds: 5 -{{- end }} - env: -{{- if .Values.external.enabled }} - - name: EXTERNAL_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "drupal.fullname" . }} - key: databasePassword -{{- else if .Values.mysql.enabled }} - - name: MYSQL_PASSWORD - valueFrom: - secretKeyRef: - name: "{{ .Release.Name }}-mysql" - key: mysql-password -{{- else if .Values.postgresql.enabled }} - - name: POSTGRES_PASSWORD - valueFrom: - secretKeyRef: - name: "{{ .Release.Name }}-postgresql" - key: password -{{- end }} -{{- if .Values.redis.enabled }} - - name: REDIS_PASSWORD - valueFrom: - secretKeyRef: - name: "{{ .Release.Name }}-redis" - key: redis-password -{{- end }} -{{- if .Values.extraVars }} -{{ toYaml .Values.extraVars | indent 8 }} -{{- end }} -{{- if .Values.drupal.resources }} - resources: -{{ toYaml .Values.drupal.resources | indent 10 }} -{{- end }} - ports: - - containerPort: 9000 - name: tcp-php-fpm - protocol: TCP - volumeMounts: - - name: cm-drupal - readOnly: true - mountPath: /usr/local/etc/php/php.ini - subPath: php.ini - - name: cm-drupal - readOnly: true - mountPath: /usr/local/etc/php/conf.d/opcache-recommended.ini - subPath: opcache-recommended.ini - - name: cm-drupal - readOnly: true - mountPath: /usr/local/etc/php-fpm.d/www.conf - subPath: www.conf - - name: cm-drupal - mountPath: /var/www/html/sites/default/settings.php - subPath: settings.php - readOnly: true - - name: cm-drupal - mountPath: /var/www/html/sites/default/extra.settings.php - subPath: extra.settings.php - readOnly: true - - name: cm-drupal - mountPath: /var/www/html/sites/default/services.yml - subPath: services.yml - readOnly: true - - name: ssmtp - mountPath: /etc/ssmtp/ssmtp.conf - subPath: ssmtp.conf - readOnly: true - - name: twig-cache - mountPath: /cache/twig -{{- if not .Values.drupal.disableDefaultFilesMount }} - - name: files - mountPath: /var/www/html/sites/default/files - subPath: public - - name: files - mountPath: /private - subPath: private -{{- end }} -{{- if not (eq .Values.drupal.siteRoot "/") }} - - name: webroot - mountPath: /webroot -{{- end }} -{{- if .Values.drupal.volumeMounts }} -{{ toYaml .Values.drupal.volumeMounts | indent 8 }} -{{- end }} -{{- if .Values.proxysql.enabled }} - - name: proxysql - image: proxysql/proxysql:2.1.0 - imagePullPolicy: Always - ports: - - containerPort: 6032 - - containerPort: 6033 - volumeMounts: - - name: configfiles - mountPath: "/etc/proxysql" - readOnly: true - livenessProbe: - tcpSocket: - port: 6032 - periodSeconds: 60 - command: ["/usr/bin/proxysql", "--initial", "-f", "-c", "/etc/proxysql/proxysql.conf"] - securityContext: - allowPrivilegeEscalation: false - runAsUser: 0 - runAsGroup: 999 -{{- else if .Values.pgbouncer.enabled }} - - name: pgbouncer - image: mcr.microsoft.com/azure-oss-db-tools/pgbouncer-sidecar:latest - imagePullPolicy: Always - ports: - - containerPort: 5432 - volumeMounts: - - name: configfiles - mountPath: "/etc/pgbouncer" - readOnly: true - livenessProbe: - tcpSocket: - port: 5432 - periodSeconds: 60 - lifecycle: - preStop: - exec: - command: ["/bin/sh", "-c", "killall -INT pgbouncer && sleep 120"] - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: ['all'] -{{- end }} - {{- if .Values.drupal.imagePullSecrets }} - imagePullSecrets: -{{ toYaml .Values.drupal.imagePullSecrets | indent 8 }} - {{- end }} - # Allow non-root user to access PersistentVolume - securityContext: -{{ toYaml .Values.drupal.securityContext | indent 8 }} - volumes: - - name: cm-drupal - configMap: - name: {{ include "drupal.fullname" . }} - - name: ssmtp - secret: - secretName: {{ include "drupal.fullname" . }}-ssmtp - items: - - key: ssmtp.conf - path: ssmtp.conf - - name: twig-cache - emptyDir: {} -{{- if .Values.drupal.persistence.enabled }} - - name: files - persistentVolumeClaim: - claimName: {{ template "drupal.fullname" . }}-drupal -{{- else if or (.Values.azure.azureFile.enabled) (.Values.azure.sharedDisk.enabled) }} - - name: files-public - persistentVolumeClaim: - claimName: {{ include "drupal.fullname" . }}-public - - name: files-private - persistentVolumeClaim: - claimName: {{ include "drupal.fullname" . }}-private -{{- else if not .Values.drupal.disableDefaultFilesMount }} - - name: files - emptyDir: {} -{{- end }} -{{- if .Values.proxysql.enabled }} - - name: configfiles - secret: - secretName: {{ include "drupal.fullname" . }}-proxysql -{{- else if .Values.pgbouncer.enabled }} - - name: configfiles - secret: - secretName: {{ include "drupal.fullname" . }}-pgbouncer -{{- end }} -{{- if not (eq .Values.drupal.siteRoot "/") }} - - name: webroot - emptyDir: {} -{{- end }} -{{- if .Values.drupal.volumes }} -{{ toYaml .Values.drupal.volumes | indent 6 }} -{{- end }} diff --git a/drupal/templates/job/post-install-site-install.yaml b/drupal/templates/job/post-install-site-install.yaml deleted file mode 100644 index ddf994c8..00000000 --- a/drupal/templates/job/post-install-site-install.yaml +++ /dev/null @@ -1,362 +0,0 @@ -{{- if .Values.drupal.install }} -apiVersion: batch/v1 -kind: Job -metadata: - name: {{ template "drupal.fullname" . }}-site-install - labels: - app.kubernetes.io/name: {{ include "drupal.name" . }} - helm.sh/chart: {{ include "drupal.chart" . }} - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - annotations: - "helm.sh/hook": post-install - "helm.sh/hook-weight": "10" - "helm.sh/hook-delete-policy": before-hook-creation -spec: - backoffLimit: {{ default "" .Values.drupal.backoffLimitInstall }} - template: - metadata: - labels: - app.kubernetes.io/name: {{ include "drupal.name" . }} - helm.sh/chart: {{ include "drupal.chart" . }} - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - spec: -{{- if .Values.drupal.tolerations }} - tolerations: -{{ toYaml .Values.drupal.tolerations | indent 6 }} -{{- end }} -{{- if .Values.drupal.nodeSelector }} - nodeSelector: -{{ toYaml .Values.drupal.nodeSelector | indent 8 }} -{{- end }} - restartPolicy: OnFailure -{{- if or (.Values.drupal.initContainers) (or (.Values.azure.azureFile.enabled) (.Values.azure.sharedDisk.enabled)) }} - initContainers: -{{- if .Values.azure.sharedDisk.enabled }} - - name: init-chown - image: 'alpine:3.10' - command: - - chown - - '-R' - - '82:82' - - /mnt/azure - volumeMounts: - - name: files-public - mountPath: /mnt/azure -{{- end }} -{{- if or (and .Values.azure.azureFile.enabled .Values.azure.azureFile.initMediaIconsFolder) (and .Values.azure.sharedDisk.enabled .Values.azure.sharedDisk.initMediaIconsFolder) }} - - name: init-media-icons-folder - image: 'alpine:3.10' - command: - - mkdir - - '-p' - - /files/media-icons/generic - volumeMounts: - - name: files-public - mountPath: /files -{{- end }} -{{- if .Values.drupal.initContainers }} -{{ toYaml .Values.drupal.initContainers | indent 8 }} -{{- end }} -{{- end }} - containers: - - name: drush - image: "{{ .Values.drupal.image }}:{{ default .Chart.AppVersion .Values.drupal.tag }}" - imagePullPolicy: {{ default "" .Values.drupal.imagePullPolicy | quote }} - command: - - '/bin/sh' - - '-c' - - | - # Errors should fail the job - set -e - - # Wait for DB to be available - {{ .Values.drupal.dbAvailabilityScript | nindent 14}} - - {{- if .Values.redis.enabled }} - {{- if .Values.redis.sentinel.enabled }} - until [[ $(printf "AUTH $REDIS_PASSWORD\r\n" | nc -w 2 {{ .Release.Name }}-redis {{ .Values.redis.sentinel.service.sentinelPort }}) == $(printf "+OK\r\n") ]]; do echo Waiting for Redis; sleep 3; done - {{- else }} - until [[ $(printf "AUTH $REDIS_PASSWORD\r\n" | nc -w 2 {{ .Release.Name }}-redis-master {{ .Values.redis.master.service.ports.redis }}) == $(printf "+OK\r\n") ]]; do echo Waiting for Redis; sleep 3; done - {{- end }} - echo Redis available - {{- end }} - - # Check Drush status - drush status || true - - {{- if .Values.redis.enabled }} - # Flush redis caches - {{- if .Values.redis.sentinel.enabled }} - printf "AUTH $REDIS_PASSWORD\r\nFLUSHDB\r\n" | nc -w 2 {{ .Release.Name }}-redis {{ .Values.redis.sentinel.service.sentinelPort }} - {{- else }} - printf "AUTH $REDIS_PASSWORD\r\nFLUSHDB\r\n" | nc -w 2 {{ .Release.Name }}-redis-master {{ .Values.redis.master.service.ports.redis }} - {{- end }} - {{- end }} - - # Run site install - {{- if .Values.drupal.restore.enabled }} - - # Check to see if using specific backup else use latest CHECK IF NAME SAYS LATEST - {{- if eq .Values.drupal.restore.name "latest"}} - BACKUPNAME=$(ls -td -- /backup/* | head -n 1 | sed -e "s/\/backup\///") - {{- else }} - BACKUPNAME='{{ .Values.drupal.restore.name }}' - {{- end }} - - echo "Restoring backup: $BACKUPNAME" - - {{- if .Values.drupal.restore.db }} - echo "Drop database" - drush sql-drop -y - echo "Restore database" - gunzip -c /backup/$BACKUPNAME/db.sql.gz{{ if .Values.drupal.restore.convert }} | sed 's/MyISAM/InnoDB/g'{{ end }} | drush sql-cli - echo "Database restored" - {{- end }} - - {{- if .Values.drupal.restore.files }} - echo "Deleting files" - # Errors from deleting should not fail the job - set +e - find sites/default/files/ -type f -print0 | xargs -0 rm - find sites/default/files/ -mindepth 1 -type d -print0 | xargs -0 rmdir - find /private/ -type f -print0 | xargs -0 rm - find /private/ -mindepth 1 -type d -print0 | xargs -0 rmdir - set -e - - echo "Restoring files" - {{- if .Values.drupal.restore.suppressTarErrors }} - set +e - {{- end }} - tar -zxf /backup/$BACKUPNAME/files.tar.gz --directory sites/default/files --no-acls --no-xattrs -m --no-same-permissions --no-overwrite-dir - tar -zxf /backup/$BACKUPNAME/private.tar.gz --directory /private --no-acls --no-xattrs -m --no-same-permissions --no-overwrite-dir - {{- if .Values.drupal.restore.suppressTarErrors }} - set -e - {{- end }} - echo "Files restored" - {{- end }} - - # Run database updates - {{- if .Values.drupal.cacheRebuildBeforeDatabaseMigration }} - drush -y cache:rebuild - {{- end }} - drush -y updatedb - - # WxT updates - {{- if .Values.drupal.wxtUpdate }} - drush -y cache:rebuild - drush -y update:wxt - {{- end }} - - {{- else }} - time drush site:install {{ .Values.drupal.profile }} \ - --sites-subdir=default \ - {{- if .Values.mysql.enabled }} - --db-url="mysql://{{ .Values.mysql.auth.username }}:$MYSQL_PASSWORD@{{ .Release.Name }}-mysql:{{ .Values.mysql.primary.service.ports.mysql }}/{{ .Values.mysql.auth.database }}" \ - {{- else if .Values.postgresql.enabled }} - --db-url="pgsql://{{ .Values.postgresql.auth.username }}:$POSTGRES_PASSWORD@{{ .Release.Name }}-postgresql:{{ .Values.postgresql.primary.service.ports.postgresql }}/{{ .Values.postgresql.auth.database }}" \ - {{- end }} - --account-name={{ .Values.drupal.username }} \ - --account-pass=$DRUPAL_ADMIN_PASSWORD \ - --site-mail={{ .Values.drupal.siteEmail | quote }} \ - --site-name={{ .Values.drupal.siteName | quote }} \ - {{- if .Values.drupal.extensions.enabled }} - wxt_extension_configure_form.select_all='TRUE' \ - {{- end }} - install_configure_form.update_status_module='array(FALSE,FALSE)' \ - --yes - {{- end }} - - drush -y cache:rebuild - - {{- if .Values.redis.enabled }} - # Enable redis - drush -y pm:enable redis - {{- end }} - - # Change WxT theme - {{- if .Values.drupal.wxtTheme }} - drush -y config:set wxt_library.settings wxt.theme '{{ .Values.drupal.wxtTheme }}' - {{- end }} - - # Rebuild caches - drush -y cache:rebuild - - # Migrate content - {{- if and .Values.drupal.migrate .Values.drupal.extensions.enabled }} - drush -y migrate:import wxt_file - drush -y migrate:import --group wxt --tag 'Core' - drush -y migrate:import --group gcweb --tag 'Core' - drush -y migrate:import --group gcweb --tag 'Menu' - {{- end }} - - # Extra installation scripts - {{- if .Values.drupal.extraInstallScripts }} - {{ .Values.drupal.extraInstallScripts | nindent 14}} - {{- end }} - env: -{{- if .Values.external.enabled }} - - name: EXTERNAL_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "drupal.fullname" . }} - key: databasePassword -{{- else if .Values.mysql.enabled }} - - name: MYSQL_PASSWORD - valueFrom: - secretKeyRef: - name: "{{ .Release.Name }}-mysql" - key: mysql-password -{{- else if .Values.postgresql.enabled }} - - name: POSTGRES_PASSWORD - valueFrom: - secretKeyRef: - name: "{{ .Release.Name }}-postgresql" - key: password -{{- end }} -{{- if .Values.redis.enabled }} - - name: REDIS_PASSWORD - valueFrom: - secretKeyRef: - name: "{{ .Release.Name }}-redis" - key: redis-password -{{- end }} - - name: DRUPAL_ADMIN_PASSWORD - valueFrom: - secretKeyRef: - name: "{{ include "drupal.fullname" . }}" - key: password -{{- if .Values.extraVars }} -{{ toYaml .Values.extraVars | indent 8 }} -{{- end }} - volumeMounts: - - name: cm-drupal - readOnly: true - mountPath: /usr/local/etc/php/php.ini - subPath: php.ini - - name: cm-drupal - readOnly: true - mountPath: /usr/local/etc/php/conf.d/opcache-recommended.ini - subPath: opcache-recommended.ini - - name: cm-drupal - readOnly: true - mountPath: /usr/local/etc/php-fpm.d/www.conf - subPath: www.conf - - name: cm-drupal - mountPath: /var/www/html/sites/default/settings.php - subPath: settings.php - readOnly: true - - name: cm-drupal - mountPath: /var/www/html/sites/default/extra.settings.php - subPath: extra.settings.php - readOnly: true - - name: cm-drupal - mountPath: /var/www/html/sites/default/services.yml - subPath: services.yml - readOnly: true - - name: twig-cache - mountPath: /cache/twig -{{- if .Values.drupal.restore.enabled }} - - name: backup - mountPath: /backup -{{- end }} -{{- if not .Values.drupal.disableDefaultFilesMount }} - - name: files - mountPath: /var/www/html/sites/default/files - subPath: public - - name: files - mountPath: /private - subPath: private -{{- end }} -{{- if .Values.drupal.volumeMounts }} -{{ toYaml .Values.drupal.volumeMounts | indent 8 }} -{{- end }} -{{- if .Values.proxysql.enabled }} - - name: proxysql - image: proxysql/proxysql:2.1.0 - imagePullPolicy: Always - ports: - - containerPort: 6032 - - containerPort: 6033 - volumeMounts: - - name: configfiles - mountPath: "/etc/proxysql" - readOnly: true - livenessProbe: - tcpSocket: - port: 6032 - periodSeconds: 60 - command: ["/usr/bin/proxysql", "--initial", "-f", "-c", "/etc/proxysql/proxysql.conf"] - securityContext: - allowPrivilegeEscalation: false - runAsUser: 0 - runAsGroup: 999 -{{- else if .Values.pgbouncer.enabled }} - - name: pgbouncer - image: mcr.microsoft.com/azure-oss-db-tools/pgbouncer-sidecar:latest - imagePullPolicy: Always - ports: - - containerPort: 5432 - volumeMounts: - - name: configfiles - mountPath: "/etc/pgbouncer" - readOnly: true - livenessProbe: - tcpSocket: - port: 5432 - periodSeconds: 60 - lifecycle: - preStop: - exec: - command: ["/bin/sh", "-c", "killall -INT pgbouncer && sleep 120"] - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: ['all'] -{{- end }} - {{- if .Values.drupal.imagePullSecrets }} - imagePullSecrets: -{{ toYaml .Values.drupal.imagePullSecrets | indent 8 }} - {{- end }} - # Allow non-root user to access PersistentVolume - securityContext: -{{ toYaml .Values.drupal.securityContext | indent 8 }} - volumes: - - name: cm-drupal - configMap: - name: {{ include "drupal.fullname" . }} - - name: twig-cache - emptyDir: {} -{{- if .Values.drupal.restore.enabled }} - - name: backup -{{ toYaml .Values.drupal.restore.volume | indent 8 }} -{{- end }} -{{- if .Values.drupal.persistence.enabled }} - - name: files - persistentVolumeClaim: - claimName: {{ template "drupal.fullname" . }}-drupal -{{- else if or (.Values.azure.azureFile.enabled) (.Values.azure.sharedDisk.enabled) }} - - name: files-public - persistentVolumeClaim: - claimName: {{ include "drupal.fullname" . }}-public - - name: files-private - persistentVolumeClaim: - claimName: {{ include "drupal.fullname" . }}-private -{{- else if not .Values.drupal.disableDefaultFilesMount }} - - name: files - emptyDir: {} -{{- end }} -{{- if .Values.proxysql.enabled }} - - name: configfiles - secret: - secretName: {{ include "drupal.fullname" . }}-proxysql -{{- else if .Values.pgbouncer.enabled }} - - name: configfiles - secret: - secretName: {{ include "drupal.fullname" . }}-pgbouncer -{{- end }} -{{- if .Values.drupal.volumes }} -{{ toYaml .Values.drupal.volumes | indent 6 }} -{{- end }} -{{- end }} diff --git a/drupal/templates/job/post-upgrade-reconfigure.yaml b/drupal/templates/job/post-upgrade-reconfigure.yaml deleted file mode 100644 index 1757b907..00000000 --- a/drupal/templates/job/post-upgrade-reconfigure.yaml +++ /dev/null @@ -1,279 +0,0 @@ -{{- if .Values.drupal.reconfigure }} -apiVersion: batch/v1 -kind: Job -metadata: - name: {{ template "drupal.fullname" . }}-reconfigure - labels: - app.kubernetes.io/name: {{ include "drupal.name" . }} - helm.sh/chart: {{ include "drupal.chart" . }} - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - annotations: - "helm.sh/hook": post-upgrade - "helm.sh/hook-weight": "10" - "helm.sh/hook-delete-policy": before-hook-creation -spec: - backoffLimit: {{ default "" .Values.drupal.backoffLimitReconfigure }} - template: - metadata: - labels: - app.kubernetes.io/name: {{ include "drupal.name" . }} - helm.sh/chart: {{ include "drupal.chart" . }} - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - spec: -{{- if .Values.drupal.tolerations }} - tolerations: -{{ toYaml .Values.drupal.tolerations | indent 6 }} -{{- end }} -{{- if .Values.drupal.nodeSelector }} - nodeSelector: -{{ toYaml .Values.drupal.nodeSelector | indent 8 }} -{{- end }} - restartPolicy: OnFailure -{{- if or (.Values.drupal.initContainers) (or (.Values.azure.azureFile.enabled) (.Values.azure.sharedDisk.enabled)) }} - initContainers: -{{- if .Values.azure.sharedDisk.enabled }} - - name: init-chown - image: 'alpine:3.10' - command: - - chown - - '-R' - - '82:82' - - /mnt/azure - volumeMounts: - - name: files-public - mountPath: /mnt/azure -{{- end }} -{{- if or (and .Values.azure.azureFile.enabled .Values.azure.azureFile.initMediaIconsFolder) (and .Values.azure.sharedDisk.enabled .Values.azure.sharedDisk.initMediaIconsFolder) }} - - name: init-media-icons-folder - image: 'alpine:3.10' - command: - - mkdir - - '-p' - - /files/media-icons/generic - volumeMounts: - - name: files-public - mountPath: /files -{{- end }} -{{- if .Values.drupal.initContainers }} -{{ toYaml .Values.drupal.initContainers | indent 8 }} -{{- end }} -{{- end }} - containers: - - name: drush - image: "{{ .Values.drupal.image }}:{{ default .Chart.AppVersion .Values.drupal.tag }}" - imagePullPolicy: {{ default "" .Values.drupal.imagePullPolicy | quote }} - command: - - '/bin/sh' - - '-c' - - | - # Errors should fail the job - set -e - - # Wait for DB to be available - {{ .Values.drupal.dbAvailabilityScript | nindent 14}} - - {{- if .Values.redis.enabled }} - {{- if .Values.redis.sentinel.enabled }} - until [[ $(printf "AUTH $REDIS_PASSWORD\r\n" | nc -w 2 {{ .Release.Name }}-redis {{ .Values.redis.sentinel.service.sentinelPort }}) == $(printf "+OK\r\n") ]]; do echo Waiting for Redis; sleep 3; done - {{- else }} - until [[ $(printf "AUTH $REDIS_PASSWORD\r\n" | nc -w 2 {{ .Release.Name }}-redis-master {{ .Values.redis.master.service.ports.redis }}) == $(printf "+OK\r\n") ]]; do echo Waiting for Redis; sleep 3; done - {{- end }} - echo Redis available - {{- end }} - - # Check Drush status - drush status || true - - # Run database updates - {{- if .Values.drupal.cacheRebuildBeforeDatabaseMigration }} - drush -y cache:rebuild - {{- end }} - {{- if .Values.drupal.updateDBBeforeDatabaseMigration }} - drush -y updatedb - {{- end }} - - # WxT updates - {{- if .Values.drupal.wxtUpdate }} - drush -y cache:rebuild - drush -y update:wxt - {{- end }} - - # Change WxT theme - {{- if .Values.drupal.wxtTheme }} - drush -y config:set wxt_library.settings wxt.theme '{{ .Values.drupal.wxtTheme }}' - {{- end }} - - # Rebuild caches - drush -y cache:rebuild - - # Migrate content - {{- if and .Values.drupal.migrate .Values.drupal.extensions.enabled }} - drush -y migrate:import wxt_file - drush -y migrate:import --group wxt --tag 'Core' - drush -y migrate:import --group gcweb --tag 'Core' - drush -y migrate:import --group gcweb --tag 'Menu' - {{- end }} - - # Extra Upgrade scripts - {{- if .Values.drupal.extraUpgradeScripts }} - {{ .Values.drupal.extraUpgradeScripts | nindent 14}} - {{- end }} - env: -{{- if .Values.external.enabled }} - - name: EXTERNAL_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "drupal.fullname" . }} - key: databasePassword -{{- else if .Values.mysql.enabled }} - - name: MYSQL_PASSWORD - valueFrom: - secretKeyRef: - name: "{{ .Release.Name }}-mysql" - key: mysql-password -{{- else if .Values.postgresql.enabled }} - - name: POSTGRES_PASSWORD - valueFrom: - secretKeyRef: - name: "{{ .Release.Name }}-postgresql" - key: password -{{- end }} -{{- if .Values.redis.enabled }} - - name: REDIS_PASSWORD - valueFrom: - secretKeyRef: - name: "{{ .Release.Name }}-redis" - key: redis-password -{{- end }} - - name: DRUPAL_ADMIN_PASSWORD - valueFrom: - secretKeyRef: - name: "{{ include "drupal.fullname" . }}" - key: password -{{- if .Values.extraVars }} -{{ toYaml .Values.extraVars | indent 8 }} -{{- end }} - volumeMounts: - - name: cm-drupal - readOnly: true - mountPath: /usr/local/etc/php/php.ini - subPath: php.ini - - name: cm-drupal - readOnly: true - mountPath: /usr/local/etc/php/conf.d/opcache-recommended.ini - subPath: opcache-recommended.ini - - name: cm-drupal - readOnly: true - mountPath: /usr/local/etc/php-fpm.d/www.conf - subPath: www.conf - - name: cm-drupal - mountPath: /var/www/html/sites/default/settings.php - subPath: settings.php - readOnly: true - - name: cm-drupal - mountPath: /var/www/html/sites/default/extra.settings.php - subPath: extra.settings.php - readOnly: true - - name: cm-drupal - mountPath: /var/www/html/sites/default/services.yml - subPath: services.yml - readOnly: true - - name: twig-cache - mountPath: /cache/twig -{{- if not .Values.drupal.disableDefaultFilesMount }} - - name: files - mountPath: /var/www/html/sites/default/files - subPath: public - - name: files - mountPath: /private - subPath: private -{{- end }} -{{- if .Values.drupal.volumeMounts }} -{{ toYaml .Values.drupal.volumeMounts | indent 8 }} -{{- end }} -{{- if .Values.proxysql.enabled }} - - name: proxysql - image: proxysql/proxysql:2.1.0 - imagePullPolicy: Always - ports: - - containerPort: 6032 - - containerPort: 6033 - volumeMounts: - - name: configfiles - mountPath: "/etc/proxysql" - readOnly: true - livenessProbe: - tcpSocket: - port: 6032 - periodSeconds: 60 - command: ["/usr/bin/proxysql", "--initial", "-f", "-c", "/etc/proxysql/proxysql.conf"] - securityContext: - allowPrivilegeEscalation: false - runAsUser: 0 - runAsGroup: 999 -{{- else if .Values.pgbouncer.enabled }} - - name: pgbouncer - image: mcr.microsoft.com/azure-oss-db-tools/pgbouncer-sidecar:latest - imagePullPolicy: Always - ports: - - containerPort: 5432 - volumeMounts: - - name: configfiles - mountPath: "/etc/pgbouncer" - readOnly: true - livenessProbe: - tcpSocket: - port: 5432 - periodSeconds: 60 - lifecycle: - preStop: - exec: - command: ["/bin/sh", "-c", "killall -INT pgbouncer && sleep 120"] - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: ['all'] -{{- end }} - {{- if .Values.drupal.imagePullSecrets }} - imagePullSecrets: -{{ toYaml .Values.drupal.imagePullSecrets | indent 8 }} - {{- end }} - # Allow non-root user to access PersistentVolume - securityContext: -{{ toYaml .Values.drupal.securityContext | indent 8 }} - volumes: - - name: cm-drupal - configMap: - name: {{ include "drupal.fullname" . }} - - name: twig-cache - emptyDir: {} -{{- if .Values.drupal.persistence.enabled }} - - name: files - persistentVolumeClaim: - claimName: {{ template "drupal.fullname" . }}-drupal -{{- else if or (.Values.azure.azureFile.enabled) (.Values.azure.sharedDisk.enabled) }} - - name: files-public - persistentVolumeClaim: - claimName: {{ include "drupal.fullname" . }}-public - - name: files-private - persistentVolumeClaim: - claimName: {{ include "drupal.fullname" . }}-private -{{- else if not .Values.drupal.disableDefaultFilesMount }} - - name: files - emptyDir: {} -{{- end }} -{{- if .Values.proxysql.enabled }} - - name: configfiles - secret: - secretName: {{ include "drupal.fullname" . }}-proxysql -{{- else if .Values.pgbouncer.enabled }} - - name: configfiles - secret: - secretName: {{ include "drupal.fullname" . }}-pgbouncer -{{- end }} -{{- if .Values.drupal.volumes }} -{{ toYaml .Values.drupal.volumes | indent 6 }} -{{- end }} -{{- end }} diff --git a/drupal/templates/pv/csi-azure-file-backup.yaml b/drupal/templates/pv/csi-azure-file-backup.yaml deleted file mode 100644 index 67dde9ca..00000000 --- a/drupal/templates/pv/csi-azure-file-backup.yaml +++ /dev/null @@ -1,31 +0,0 @@ -{{- if .Values.azure.azureFile.enabled -}} -{{- if not .Values.azure.azureFile.disablePVCreation }} -apiVersion: v1 -kind: PersistentVolume -metadata: -{{- if .Values.azure.azureFile.annotations }} - annotations: -{{ toYaml .Values.azure.azureFile.annotations | indent 4 }} -{{- end }} - name: {{ include "drupal.fullname" . }}-backup -spec: - capacity: - storage: {{ .Values.azure.azureFile.size }} - accessModes: - - {{ .Values.azure.azureFile.accessMode }} -{{- if .Values.azure.storageClass.create }} - storageClassName: {{ include "drupal.fullname" . }}-csi-azure -{{- else if eq "-" .Values.azure.azureFile.storageClass }} - storageClassName: "" -{{- else if .Values.azure.azureFile.storageClass }} - storageClassName: "{{ .Values.azure.azureFile.storageClass }}" -{{- end }} -{{- if .Values.azure.azureFile.backup.spec }} -{{ toYaml .Values.azure.azureFile.backup.spec | indent 2 }} -{{- end }} -{{- if .Values.azure.azureFile.backup.mountOptions }} - mountOptions: -{{ toYaml .Values.azure.azureFile.backup.mountOptions | indent 4 }} -{{- end }} -{{- end }} -{{- end }} diff --git a/drupal/templates/pv/csi-azure-file-private.yaml b/drupal/templates/pv/csi-azure-file-private.yaml deleted file mode 100644 index 8c1718ba..00000000 --- a/drupal/templates/pv/csi-azure-file-private.yaml +++ /dev/null @@ -1,31 +0,0 @@ -{{- if .Values.azure.azureFile.enabled -}} -{{- if not .Values.azure.azureFile.disablePVCreation }} -apiVersion: v1 -kind: PersistentVolume -metadata: -{{- if .Values.azure.azureFile.annotations }} - annotations: -{{ toYaml .Values.azure.azureFile.annotations | indent 4 }} -{{- end }} - name: {{ include "drupal.fullname" . }}-private -spec: - capacity: - storage: {{ .Values.azure.azureFile.size }} - accessModes: - - {{ .Values.azure.azureFile.accessMode }} -{{- if .Values.azure.storageClass.create }} - storageClassName: {{ include "drupal.fullname" . }}-csi-azure -{{- else if eq "-" .Values.azure.azureFile.storageClass }} - storageClassName: "" -{{- else if .Values.azure.azureFile.storageClass }} - storageClassName: "{{ .Values.azure.azureFile.storageClass }}" -{{- end }} -{{- if .Values.azure.azureFile.private.spec }} -{{ toYaml .Values.azure.azureFile.private.spec | indent 2 }} -{{- end }} -{{- if .Values.azure.azureFile.private.mountOptions }} - mountOptions: -{{ toYaml .Values.azure.azureFile.private.mountOptions | indent 4 }} -{{- end }} -{{- end }} -{{- end }} diff --git a/drupal/templates/pv/csi-azure-file-public.yaml b/drupal/templates/pv/csi-azure-file-public.yaml deleted file mode 100644 index cecd704b..00000000 --- a/drupal/templates/pv/csi-azure-file-public.yaml +++ /dev/null @@ -1,31 +0,0 @@ -{{- if .Values.azure.azureFile.enabled -}} -{{- if not .Values.azure.azureFile.disablePVCreation }} -apiVersion: v1 -kind: PersistentVolume -metadata: -{{- if .Values.azure.azureFile.annotations }} - annotations: -{{ toYaml .Values.azure.azureFile.annotations | indent 4 }} -{{- end }} - name: {{ include "drupal.fullname" . }}-public -spec: - capacity: - storage: {{ .Values.azure.azureFile.size }} - accessModes: - - {{ .Values.azure.azureFile.accessMode }} -{{- if .Values.azure.storageClass.create }} - storageClassName: {{ include "drupal.fullname" . }}-csi-azure -{{- else if eq "-" .Values.azure.azureFile.storageClass }} - storageClassName: "" -{{- else if .Values.azure.azureFile.storageClass }} - storageClassName: "{{ .Values.azure.azureFile.storageClass }}" -{{- end }} -{{- if .Values.azure.azureFile.public.spec }} -{{ toYaml .Values.azure.azureFile.public.spec | indent 2 }} -{{- end }} -{{- if .Values.azure.azureFile.public.mountOptions }} - mountOptions: -{{ toYaml .Values.azure.azureFile.public.mountOptions | indent 4 }} -{{- end }} -{{- end }} -{{- end }} diff --git a/drupal/templates/pv/csi-azure-file-tmp.yaml b/drupal/templates/pv/csi-azure-file-tmp.yaml deleted file mode 100644 index b7243653..00000000 --- a/drupal/templates/pv/csi-azure-file-tmp.yaml +++ /dev/null @@ -1,31 +0,0 @@ -{{- if .Values.azure.azureFile.enabled -}} -{{- if not .Values.azure.azureFile.disablePVCreation }} -apiVersion: v1 -kind: PersistentVolume -metadata: -{{- if .Values.azure.azureFile.annotations }} - annotations: -{{ toYaml .Values.azure.azureFile.annotations | indent 4 }} -{{- end }} - name: {{ include "drupal.fullname" . }}-tmp -spec: - capacity: - storage: {{ .Values.azure.azureFile.size }} - accessModes: - - {{ .Values.azure.azureFile.accessMode }} -{{- if .Values.azure.storageClass.create }} - storageClassName: {{ include "drupal.fullname" . }}-csi-azure -{{- else if eq "-" .Values.azure.azureFile.storageClass }} - storageClassName: "" -{{- else if .Values.azure.azureFile.storageClass }} - storageClassName: "{{ .Values.azure.azureFile.storageClass }}" -{{- end }} -{{- if .Values.azure.azureFile.tmp.spec }} -{{ toYaml .Values.azure.azureFile.tmp.spec | indent 2 }} -{{- end }} -{{- if .Values.azure.azureFile.tmp.mountOptions }} - mountOptions: -{{ toYaml .Values.azure.azureFile.tmp.mountOptions | indent 4 }} -{{- end }} -{{- end }} -{{- end }} diff --git a/drupal/templates/pv/csi-azure-shared-disk-private.yaml b/drupal/templates/pv/csi-azure-shared-disk-private.yaml deleted file mode 100644 index 39ebab21..00000000 --- a/drupal/templates/pv/csi-azure-shared-disk-private.yaml +++ /dev/null @@ -1,31 +0,0 @@ -{{- if .Values.azure.sharedDisk.enabled }} -{{- if not .Values.azure.sharedDisk.disablePVCreation }} -apiVersion: v1 -kind: PersistentVolume -metadata: -{{- if .Values.azure.sharedDisk.annotations }} - annotations: -{{ toYaml .Values.azure.sharedDisk.annotations | indent 4 }} -{{- end }} - name: {{ include "drupal.fullname" . }}-private -spec: - capacity: - storage: {{ .Values.azure.sharedDisk.size }} - accessModes: - - {{ .Values.azure.sharedDisk.accessMode }} -{{- if .Values.azure.storageClass.create }} - storageClassName: {{ include "drupal.fullname" . }}-csi-azure -{{- else if eq "-" .Values.azure.sharedDisk.storageClass }} - storageClassName: "" -{{- else if .Values.azure.sharedDisk.storageClass }} - storageClassName: "{{ .Values.azure.sharedDisk.storageClass }}" -{{- end }} -{{- if .Values.azure.sharedDisk.private.spec }} -{{ toYaml .Values.azure.sharedDisk.private.spec | indent 2 }} -{{- end }} -{{- if .Values.azure.sharedDisk.private.mountOptions }} - mountOptions: -{{ toYaml .Values.azure.sharedDisk.private.mountOptions | indent 4 }} -{{- end }} -{{- end }} -{{- end }} diff --git a/drupal/templates/pv/csi-azure-shared-disk-public.yaml b/drupal/templates/pv/csi-azure-shared-disk-public.yaml deleted file mode 100644 index 367e00b3..00000000 --- a/drupal/templates/pv/csi-azure-shared-disk-public.yaml +++ /dev/null @@ -1,31 +0,0 @@ -{{- if .Values.azure.sharedDisk.enabled }} -{{- if not .Values.azure.sharedDisk.disablePVCreation }} -apiVersion: v1 -kind: PersistentVolume -metadata: -{{- if .Values.azure.sharedDisk.annotations }} - annotations: -{{ toYaml .Values.azure.sharedDisk.annotations | indent 4 }} -{{- end }} - name: {{ include "drupal.fullname" . }}-public -spec: - capacity: - storage: {{ .Values.azure.sharedDisk.size }} - accessModes: - - {{ .Values.azure.sharedDisk.accessMode }} -{{- if .Values.azure.storageClass.create }} - storageClassName: {{ include "drupal.fullname" . }}-csi-azure -{{- else if eq "-" .Values.azure.sharedDisk.storageClass }} - storageClassName: "" -{{- else if .Values.azure.sharedDisk.storageClass }} - storageClassName: "{{ .Values.azure.sharedDisk.storageClass }}" -{{- end }} -{{- if .Values.azure.sharedDisk.public.spec }} -{{ toYaml .Values.azure.sharedDisk.public.spec | indent 2 }} -{{- end }} -{{- if .Values.azure.sharedDisk.public.mountOptions }} - mountOptions: -{{ toYaml .Values.azure.sharedDisk.public.mountOptions | indent 4 }} -{{- end }} -{{- end }} -{{- end }} diff --git a/drupal/templates/pvc/csi-azure-file-backup.yaml b/drupal/templates/pvc/csi-azure-file-backup.yaml deleted file mode 100644 index 36da8b38..00000000 --- a/drupal/templates/pvc/csi-azure-file-backup.yaml +++ /dev/null @@ -1,26 +0,0 @@ -{{- if .Values.azure.azureFile.enabled }} -kind: PersistentVolumeClaim -apiVersion: v1 -metadata: - annotations: -{{- if .Values.azure.azureFile.enabled }} -{{ toYaml .Values.azure.azureFile.annotations | indent 4 }} -{{- end }} - name: {{ include "drupal.fullname" . }}-backup -spec: - accessModes: - - {{ .Values.azure.azureFile.accessMode }} - resources: - requests: - storage: {{ .Values.azure.azureFile.size }} -{{- if not .Values.azure.azureFile.disableVolumeName }} - volumeName: {{ include "drupal.fullname" . }}-backup -{{- end }} -{{- if .Values.azure.storageClass.create }} - storageClassName: {{ include "drupal.fullname" . }}-csi-azure -{{- else if eq "-" .Values.azure.azureFile.storageClass }} - storageClassName: "" -{{- else if .Values.azure.azureFile.storageClass }} - storageClassName: "{{ .Values.azure.azureFile.storageClass }}" -{{- end }} -{{- end }} diff --git a/drupal/templates/pvc/csi-azure-file-private.yaml b/drupal/templates/pvc/csi-azure-file-private.yaml deleted file mode 100644 index b403589e..00000000 --- a/drupal/templates/pvc/csi-azure-file-private.yaml +++ /dev/null @@ -1,26 +0,0 @@ -{{- if .Values.azure.azureFile.enabled }} -kind: PersistentVolumeClaim -apiVersion: v1 -metadata: - annotations: -{{- if .Values.azure.azureFile.enabled }} -{{ toYaml .Values.azure.azureFile.annotations | indent 4 }} -{{- end }} - name: {{ include "drupal.fullname" . }}-private -spec: - accessModes: - - {{ .Values.azure.azureFile.accessMode }} - resources: - requests: - storage: {{ .Values.azure.azureFile.size }} -{{- if not .Values.azure.azureFile.disableVolumeName }} - volumeName: {{ include "drupal.fullname" . }}-private -{{- end }} -{{- if .Values.azure.storageClass.create }} - storageClassName: {{ include "drupal.fullname" . }}-csi-azure -{{- else if eq "-" .Values.azure.azureFile.storageClass }} - storageClassName: "" -{{- else if .Values.azure.azureFile.storageClass }} - storageClassName: "{{ .Values.azure.azureFile.storageClass }}" -{{- end }} -{{- end }} diff --git a/drupal/templates/pvc/csi-azure-file-public.yaml b/drupal/templates/pvc/csi-azure-file-public.yaml deleted file mode 100644 index fb03432f..00000000 --- a/drupal/templates/pvc/csi-azure-file-public.yaml +++ /dev/null @@ -1,26 +0,0 @@ -{{- if .Values.azure.azureFile.enabled }} -kind: PersistentVolumeClaim -apiVersion: v1 -metadata: - annotations: -{{- if .Values.azure.azureFile.enabled }} -{{ toYaml .Values.azure.azureFile.annotations | indent 4 }} -{{- end }} - name: {{ include "drupal.fullname" . }}-public -spec: - accessModes: - - {{ .Values.azure.azureFile.accessMode }} - resources: - requests: - storage: {{ .Values.azure.azureFile.size }} -{{- if not .Values.azure.azureFile.disableVolumeName }} - volumeName: {{ include "drupal.fullname" . }}-public -{{- end }} -{{- if .Values.azure.storageClass.create }} - storageClassName: {{ include "drupal.fullname" . }}-csi-azure -{{- else if eq "-" .Values.azure.azureFile.storageClass }} - storageClassName: "" -{{- else if .Values.azure.azureFile.storageClass }} - storageClassName: "{{ .Values.azure.azureFile.storageClass }}" -{{- end }} -{{- end }} diff --git a/drupal/templates/pvc/csi-azure-file-tmp.yaml b/drupal/templates/pvc/csi-azure-file-tmp.yaml deleted file mode 100644 index c00f367d..00000000 --- a/drupal/templates/pvc/csi-azure-file-tmp.yaml +++ /dev/null @@ -1,26 +0,0 @@ -{{- if .Values.azure.azureFile.enabled }} -kind: PersistentVolumeClaim -apiVersion: v1 -metadata: - annotations: -{{- if .Values.azure.azureFile.enabled }} -{{ toYaml .Values.azure.azureFile.annotations | indent 4 }} -{{- end }} - name: {{ include "drupal.fullname" . }}-tmp -spec: - accessModes: - - {{ .Values.azure.azureFile.accessMode }} - resources: - requests: - storage: {{ .Values.azure.azureFile.size }} -{{- if not .Values.azure.azureFile.disableVolumeName }} - volumeName: {{ include "drupal.fullname" . }}-tmp -{{- end }} -{{- if .Values.azure.storageClass.create }} - storageClassName: {{ include "drupal.fullname" . }}-csi-azure -{{- else if eq "-" .Values.azure.azureFile.storageClass }} - storageClassName: "" -{{- else if .Values.azure.azureFile.storageClass }} - storageClassName: "{{ .Values.azure.azureFile.storageClass }}" -{{- end }} -{{- end }} diff --git a/drupal/templates/pvc/csi-azure-shared-disk-private.yaml b/drupal/templates/pvc/csi-azure-shared-disk-private.yaml deleted file mode 100644 index 72c352ea..00000000 --- a/drupal/templates/pvc/csi-azure-shared-disk-private.yaml +++ /dev/null @@ -1,26 +0,0 @@ -{{- if .Values.azure.sharedDisk.enabled }} -kind: PersistentVolumeClaim -apiVersion: v1 -metadata: - annotations: -{{- if .Values.azure.sharedDisk.enabled }} -{{ toYaml .Values.azure.sharedDisk.annotations | indent 4 }} -{{- end }} - name: {{ include "drupal.fullname" . }}-private -spec: - accessModes: - - {{ .Values.azure.sharedDisk.accessMode }} - resources: - requests: - storage: {{ .Values.azure.sharedDisk.size }} -{{- if not .Values.azure.sharedDisk.disableVolumeName }} - volumeName: {{ include "drupal.fullname" . }}-private -{{- end }} -{{- if .Values.azure.storageClass.create }} - storageClassName: {{ include "drupal.fullname" . }}-csi-azure -{{- else if eq "-" .Values.azure.sharedDisk.storageClass }} - storageClassName: "" -{{- else if .Values.azure.sharedDisk.storageClass }} - storageClassName: "{{ .Values.azure.sharedDisk.storageClass }}" -{{- end }} -{{- end }} diff --git a/drupal/templates/pvc/csi-azure-shared-disk-public.yaml b/drupal/templates/pvc/csi-azure-shared-disk-public.yaml deleted file mode 100644 index 7ad39f3c..00000000 --- a/drupal/templates/pvc/csi-azure-shared-disk-public.yaml +++ /dev/null @@ -1,26 +0,0 @@ -{{- if .Values.azure.sharedDisk.enabled }} -kind: PersistentVolumeClaim -apiVersion: v1 -metadata: - annotations: -{{- if .Values.azure.sharedDisk.enabled }} -{{ toYaml .Values.azure.sharedDisk.annotations | indent 4 }} -{{- end }} - name: {{ include "drupal.fullname" . }}-public -spec: - accessModes: - - {{ .Values.azure.sharedDisk.accessMode }} - resources: - requests: - storage: {{ .Values.azure.sharedDisk.size }} -{{- if not .Values.azure.sharedDisk.disableVolumeName }} - volumeName: {{ include "drupal.fullname" . }}-public -{{- end }} -{{- if .Values.azure.storageClass.create }} - storageClassName: {{ include "drupal.fullname" . }}-csi-azure -{{- else if eq "-" .Values.azure.sharedDisk.storageClass }} - storageClassName: "" -{{- else if .Values.azure.sharedDisk.storageClass }} - storageClassName: "{{ .Values.azure.sharedDisk.storageClass }}" -{{- end }} -{{- end }} diff --git a/drupal/values-example-csi-azure.yaml b/drupal/values-example-csi-azure.yaml deleted file mode 100644 index 92bae7c6..00000000 --- a/drupal/values-example-csi-azure.yaml +++ /dev/null @@ -1,291 +0,0 @@ -# Default values for Site Example CSI Azure. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -ingress: - enabled: true - path: / - hosts: - - site.example.ca - annotations: - kubernetes.io/ingress.class: istio - -## Drupal -## Ref: https://github.com/drupalwxt/helm-drupal -drupal: - ## Drupal image version - ## ref: https://hub.docker.com/drupalwxt/site-wxt/tags/ - ## - image: example.azurecr.io/site-example - tag: 1.0.0 - version: d9 - - imagePullSecrets: - - name: acr-registry - - ## Site configuration - ## - profile: wxt - siteEmail: admin@example.com - siteName: Drupal Install Profile (WxT) - - ## Application password - ## - password: XXXXX - - # php-fpm healthcheck - # Requires https://github.com/renatomefi/php-fpm-healthcheck in the container. - # (note: official images do not contain this feature yet) - healthcheck: - enabled: true - - # Switch to canada.ca theme (only used if install and/or reconfigure are enabled) - # Common options include: theme-wet-boew, theme-gcweb-legacy - wxtTheme: theme-gcweb - - # Install Drupal automatically - install: false - - # Run migrations for default content - migrate: false - - # PHP configuration - php: - ini: - mysqlnd_azure.enableRedirect: off - - # Reconfigure on upgrade - reconfigure: true - cacheRebuildBeforeDatabaseMigration: true - - # Run extra install scripts - # extraInstallScripts: |- - # - - ## Extra settings.php settings - ## - extraSettings: |- - $databases['default']['default']['pdo'][PDO::MYSQL_ATTR_SSL_CA] = '/etc/ssl/certs/ca-certificates.crt'; - $_SERVER['HTTPS'] = $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https' ? 'on' : 'off'; - $_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST']; - $settings['file_temp_path'] = '/drupal-tmp'; - $config['config_split.config_split.dev']['status'] = TRUE; - - extraUpgradeScripts: |- - drush config:import --yes - - # Restore Drupal automatically - restore: - enabled: false - - # Configure the Drupal cron - cron: - # When enabled, a CronJob will run the job based on the schedule - enabled: true - - # CronJob schedule (standard cron syntax) - # Defaults to once an hour - schedule: '*/2 * * * *' - - # Configure additional Drupal crons - additionalCrons: - clean-backups: - # Run at 03:00AM UTC every day. - schedule: '00 03 * * *' - script: | - find /backup/ -mindepth 1 -maxdepth 1 -type d -mtime +30 -exec echo "rm -rf " {} \; 2>&1; - find /backup/ -mindepth 1 -maxdepth 1 -type d -mtime +30 -exec rm -rf {} \; 2>&1; - - volumes: - - name: backup - persistentVolumeClaim: - claimName: example-drupal-backup - - volumeMounts: - - name: backup - mountPath: /backup - - # Configure the Drupal backup cron - backup: - # When enabled, a CronJob will run the job based on the schedule - enabled: true - - # CronJob schedule (standard cron syntax) - # Defaults to midnight - schedule: '0 0 * * *' - - volume: - persistentVolumeClaim: - claimName: example-drupal-backup - - # Allows custom /var/www/html/sites/default/files and /var/www/private mounts - disableDefaultFilesMount: true - - volumes: - - name: files-tmp - persistentVolumeClaim: - claimName: example-drupal-tmp - - volumeMounts: - - name: files-public - mountPath: /var/www/html/sites/default/files - - name: files-private - mountPath: /private - - name: files-tmp - mountPath: /drupal-tmp - - configSync: - directory: "/var/www/config/sync" - -## Nginx -## Ref: https://github.com/drupalwxt/helm-drupal -nginx: - image: example.azurecr.io/site-example-nginx - tag: 1.0.0 - - imagePullSecrets: - - name: acr-registry - - # Set your cluster's DNS resolution service here - resolver: 10.0.0.10 - - volumeMounts: - - name: files-public - mountPath: /var/www/html/sites/default/files - -azure: - storageClass: - create: true - - ## Azure Files - # kubectl create secret generic example-storage --from-literal=azurestorageaccountname=$STORAGE_ACCOUNT_NAME --from-literal=azurestorageaccountkey=$STORAGE_KEY -n catsa - azureFile: - enabled: true - # storageClass: "-" - - size: 100Gi - - protocol: nfs - - public: - spec: - csi: - driver: file.csi.azure.com - volumeHandle: "example-drupal-public-nfs" - volumeAttributes: - resourceGroup: "dev-cc-drupal" - storageAccount: "devccdrupal" - shareName: public - protocol: nfs - - private: - spec: - csi: - driver: file.csi.azure.com - volumeHandle: "example-drupal-private-nfs" - volumeAttributes: - resourceGroup: "dev-cc-drupal" - storageAccount: "devccdrupal" - shareName: public - protocol: nfs - - backup: - spec: - csi: - driver: file.csi.azure.com - volumeHandle: "example-drupal-backup-nfs" - volumeAttributes: - resourceGroup: "dev-cc-drupal" - storageAccount: "devccdrupal" - shareName: backup - protocol: nfs - tmp: - spec: - csi: - driver: file.csi.azure.com - volumeHandle: "example-drupal-tmp-nfs" - volumeAttributes: - resourceGroup: "dev-cc-drupal" - storageAccount: "devccdrupal" - shareName: tmp - protocol: nfs - -## Redis -## Ref: https://github.com/bitnami/charts/tree/master/bitnami/redis -redis: - enabled: true - global: - redis: - password: XXXXX - image: - pullSecrets: - - acr-registry - replica: - enabled: false - replicaCount: 0 - service: - type: ClusterIP - disableCommands: [] - persistence: - enabled: false - sentinel: - enabled: false - master: - service: - type: ClusterIP - disableCommands: [] - persistence: - enabled: false - livenessProbe: - enabled: true - initialDelaySeconds: 20 - periodSeconds: 5 - timeoutSeconds: 5 - successThreshold: 1 - failureThreshold: 5 - readinessProbe: - enabled: true - initialDelaySeconds: 20 - periodSeconds: 5 - timeoutSeconds: 5 - successThreshold: 1 - failureThreshold: 5 - commonConfiguration: |- - # Disable AOF https://redis.io/topics/persistence#append-only-file - appendonly no - # Disable RDB persistence. - save "" - # Redis Memory - maxmemory "8024mb" - maxmemory-policy "volatile-lfu" - -## Varnish -## Ref: https://github.com/StatCan/charts/tree/master/stable/varnish -varnish: - enabled: true - varnishd: - image: docker.io/varnish - imagePullSecrets: - - name: acr-registry - memorySize: 1G - -## External DB -## Ref: https://github.com/drupalwxt/helm-drupal -external: - enabled: true - driver: mysql - port: 3306 - host: XXXXX.mysql.database.azure.com - database: "example" - user: examplemysqladmin - password: XXXXX - -## MySQL -## Ref: https://github.com/bitnami/charts/tree/master/bitnami/mysql -mysql: - enabled: false - -## ProxySQL -## Ref: https://github.com/drupalwxt/helm-drupal -proxysql: - enabled: false diff --git a/drupal/values-example-single-node.yaml b/drupal/values-example-single-node.yaml deleted file mode 100644 index 18628f3d..00000000 --- a/drupal/values-example-single-node.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# Default values for Site Example Single Node. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -drupal: - persistence: - enabled: true - ## A manually managed Persistent Volume and Claim - ## Requires persistence.enabled: true - ## If defined, PVC must be created manually before volume will be bound - # existingClaim: - - ## Drupal data Persistent Volume Storage Class - ## If defined, storageClassName: - ## If set to "-", storageClassName: "", which disables dynamic provisioning - ## If undefined (the default) or set to null, no storageClassName spec is - ## set, choosing the default provisioner. (gp2 on AWS, standard on - ## GKE, AWS & OpenStack) - ## - # storageClass: "-" - annotations: {} - accessMode: ReadWriteOnce - size: 8Gi diff --git a/drupal7/Chart.yaml b/drupal7/Chart.yaml deleted file mode 100644 index 34fd9dd0..00000000 --- a/drupal7/Chart.yaml +++ /dev/null @@ -1,41 +0,0 @@ -name: drupal7 -apiVersion: v2 -type: application -version: 0.3.5 -appVersion: "4.54" -description: Drupal 7 variant of the Web Experience Toolkit (WetKit). -keywords: -- drupal -- cms -- wetkit -- http -- web -- application -- php -home: http://www.drupal.org/project/wetkit -icon: https://bitnami.com/assets/stacks/drupal/img/drupal-stack-220x234.png -sources: -- https://github.com/wet-boew/wet-boew-drupal -maintainers: -- name: sylus - email: william.hearn@canada.ca -- name: zachomedia - email: zachary.seguin@canada.ca -engine: gotpl -dependencies: - - name: mysql - version: 9.1.7 - repository: https://charts.bitnami.com/bitnami - condition: mysql.enabled - - name: postgresql - version: 11.6.6 - repository: https://charts.bitnami.com/bitnami - condition: postgresql.enabled - - name: redis - version: 16.13.2 - repository: https://charts.bitnami.com/bitnami - condition: redis.enabled - - name: varnish - version: 0.2.2 - repository: https://statcan.github.io/charts - condition: varnish.enabled diff --git a/drupal7/README.md b/drupal7/README.md deleted file mode 100644 index 6dac0a9c..00000000 --- a/drupal7/README.md +++ /dev/null @@ -1,291 +0,0 @@ -# drupal7 - -![Version: 0.3.5](https://img.shields.io/badge/Version-0.3.5-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 4.54](https://img.shields.io/badge/AppVersion-4.54-informational?style=flat-square) - -Drupal 7 variant of the Web Experience Toolkit (WetKit). - -**Homepage:** - -## Maintainers - -| Name | Email | Url | -| ---- | ------ | --- | -| sylus | | | -| zachomedia | | | - -## Source Code - -* - -## Requirements - -| Repository | Name | Version | -|------------|------|---------| -| https://charts.bitnami.com/bitnami | mysql | 9.1.7 | -| https://charts.bitnami.com/bitnami | postgresql | 11.6.6 | -| https://charts.bitnami.com/bitnami | redis | 16.13.2 | -| https://statcan.github.io/charts | varnish | 0.2.2 | - -## Prerequisites - -- Kubernetes 1.7+ -- Helm v3.0.0+ - -## Installing the Chart - -To install the chart with the release name `my-release`: - -```sh -helm repo add drupalwxt https://drupalwxt.github.io/helm-drupal -"drupalwxt" has been added to your repositories - -helm install my-release drupalwxt/drupal -NAME: my-release -``` - -Optionally you can git clone the helm chart and select the appropriate values file: - -```sh -git clone https://github.com/drupalwxt/helm-drupal -cd helm-drupal/drupal -cp values-azurefile.yaml values-override.yaml -helm install --name drupal -f values-override.yaml -``` - -## Ingress - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| ingress.annotations | object | `{}` | | -| ingress.enabled | bool | `false` | | -| ingress.hosts[0] | string | `"chart-example.local"` | | -| ingress.path | string | `"/"` | | -| ingress.tls | list | `[]` | | - -## Drupal - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| drupal.additionalCrons | object | `{}` | | -| drupal.autoscaling.enabled | bool | `false` | | -| drupal.autoscaling.maxReplicas | int | `11` | | -| drupal.autoscaling.minReplicas | int | `1` | | -| drupal.autoscaling.targetCPUUtilizationPercentage | int | `50` | | -| drupal.autoscaling.targetMemoryUtilizationPercentage | int | `50` | | -| drupal.backup.enabled | bool | `false` | | -| drupal.backup.filesArgs | string | `""` | | -| drupal.backup.privateArgs | string | `""` | | -| drupal.backup.schedule | string | `"0 0 * * *"` | | -| drupal.backup.sqlDumpArgs | string | `""` | | -| drupal.backup.volume | object | `{}` | | -| drupal.cacheRebuildBeforeDatabaseMigration | bool | `true` | | -| drupal.cron.enabled | bool | `true` | | -| drupal.cron.schedule | string | `"0 * * * *"` | | -| drupal.dbAvailabilityScript | string | `"until drush sql:query 'SHOW TABLES;'; do echo Waiting for DB; sleep 3; done\necho DB available"` | default script used to detect when the DB is ready | -| drupal.disableDefaultFilesMount | bool | `false` | | -| drupal.extraInstallScripts | string | `""` | | -| drupal.extraSettings | string | `""` | | -| drupal.extraUpgradeScripts | string | `""` | | -| drupal.healthcheck.enabled | bool | `true` | | -| drupal.image | string | `"drupalwxt/site-wetkit"` | | -| drupal.imagePullPolicy | string | `"IfNotPresent"` | | -| drupal.install | bool | `true` | | -| drupal.migrate | bool | `false` | | -| drupal.nodeSelector | object | `{}` | | -| drupal.persistence.accessMode | string | `"ReadWriteOnce"` | | -| drupal.persistence.annotations | object | `{}` | | -| drupal.persistence.enabled | bool | `false` | | -| drupal.persistence.size | string | `"8Gi"` | | -| drupal.php.ini | object | `{}` | | -| drupal.podAnnotations | object | `{}` | | -| drupal.profile | string | `"wetkit"` | | -| drupal.reconfigure | bool | `true` | | -| drupal.replicas | int | `1` | | -| drupal.resources | object | `{}` | | -| drupal.restore.convert | bool | `false` | | -| drupal.restore.db | bool | `true` | | -| drupal.restore.enabled | bool | `false` | | -| drupal.restore.files | bool | `false` | | -| drupal.restore.name | string | `"latest"` | | -| drupal.restore.suppressTarErrors | bool | `false` | | -| drupal.restore.volume | object | `{}` | | -| drupal.securityContext.fsGroup | int | `82` | | -| drupal.securityContext.runAsGroup | int | `82` | | -| drupal.securityContext.runAsUser | int | `82` | | -| drupal.serviceType | string | `"ClusterIP"` | | -| drupal.siteEmail | string | `"admin@example.com"` | | -| drupal.siteName | string | `"Drupal Install Profile (WetKit)"` | | -| drupal.smtp.auth.enabled | bool | `false` | | -| drupal.smtp.auth.method | string | `"LOGIN"` | | -| drupal.smtp.auth.password | string | `""` | | -| drupal.smtp.auth.user | string | `""` | | -| drupal.smtp.host | string | `"mail"` | | -| drupal.smtp.starttls | bool | `true` | | -| drupal.smtp.tls | bool | `true` | | -| drupal.tolerations | list | `[]` | | -| drupal.updateDBBeforeDatabaseMigration | bool | `true` | | -| drupal.username | string | `"admin"` | | -| drupal.version | string | `"d7"` | | -| drupal.volumeMounts | string | `nil` | | -| drupal.volumes | string | `nil` | | -| drupal.wxtTheme | string | `"theme-gcweb"` | | - -## Nginx - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| nginx.autoscaling.enabled | bool | `false` | | -| nginx.autoscaling.maxReplicas | int | `11` | | -| nginx.autoscaling.minReplicas | int | `1` | | -| nginx.autoscaling.targetCPUUtilizationPercentage | int | `50` | | -| nginx.autoscaling.targetMemoryUtilizationPercentage | int | `50` | | -| nginx.client_max_body_size | string | `"20m"` | | -| nginx.customLocations | string | `""` | | -| nginx.gzip | bool | `true` | | -| nginx.image | string | `"drupalwxt/site-wetkit"` | | -| nginx.imagePullPolicy | string | `"IfNotPresent"` | | -| nginx.nodeSelector | object | `{}` | | -| nginx.real_ip_header | string | `"X-Forwarded-For"` | | -| nginx.replicas | int | `1` | | -| nginx.resolver | string | `"kube-dns.kube-system.svc.cluster.local"` | | -| nginx.securityContext.enabled | bool | `true` | | -| nginx.securityContext.fsGroup | int | `33` | | -| nginx.serviceType | string | `"ClusterIP"` | | -| nginx.tolerations | list | `[]` | | -| nginx.volumeMounts | string | `nil` | | -| nginx.volumes | string | `nil` | | - -## MySQL - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| mysql.auth.database | string | `"wxt"` | | -| mysql.auth.password | string | `""` | | -| mysql.auth.rootPassword | string | `""` | | -| mysql.auth.username | string | `"wxt"` | | -| mysql.enabled | bool | `true` | | -| mysql.image.tag | string | `"8.0.29-debian-11-r3"` | | -| mysql.primary.configuration | string | `"[mysqld]\ndefault_authentication_plugin=mysql_native_password\nskip-name-resolve\nexplicit_defaults_for_timestamp\nbasedir=/opt/bitnami/mysql\nplugin_dir=/opt/bitnami/mysql/lib/plugin\nport=3306\nsocket=/opt/bitnami/mysql/tmp/mysql.sock\ndatadir=/bitnami/mysql/data\ntmpdir=/opt/bitnami/mysql/tmp\nmax_allowed_packet=16M\nbind-address=0.0.0.0\npid-file=/opt/bitnami/mysql/tmp/mysqld.pid\nlog-error=/opt/bitnami/mysql/logs/mysqld.log\ncharacter-set-server=UTF8\ncollation-server=utf8_general_ci\nslow_query_log=0\nslow_query_log_file=/opt/bitnami/mysql/logs/mysqld.log\nlong_query_time=10.0\n\nmax_allowed_packet = 256M\ninnodb_buffer_pool_size = 4096M\ninnodb_buffer_pool_instances = 4\ntable_definition_cache = 4096\ntable_open_cache = 8192\ninnodb_flush_log_at_trx_commit=2\n[client]\nport=3306\nsocket=/opt/bitnami/mysql/tmp/mysql.sock\ndefault-character-set=UTF8\nplugin_dir=/opt/bitnami/mysql/lib/plugin\n[manager]\nport=3306\nsocket=/opt/bitnami/mysql/tmp/mysql.sock\npid-file=/opt/bitnami/mysql/tmp/mysqld.pid"` | | -| mysql.primary.persistence.enabled | bool | `true` | | -| mysql.primary.persistence.size | string | `"128Gi"` | | -| mysql.volumePermissions.enabled | bool | `true` | | - -### ProxySQL - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| proxysql.admin.password | string | `"password"` | | -| proxysql.admin.user | string | `"username@hostname"` | | -| proxysql.configuration.maxConnections | int | `2048` | | -| proxysql.configuration.serverVersion | string | `"5.7.28"` | | -| proxysql.configuration.stackSize | int | `1048576` | | -| proxysql.enabled | bool | `false` | | -| proxysql.monitor.password | string | `"password"` | | -| proxysql.monitor.user | string | `"username@hostname"` | | - -## PostgreSQL - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| postgresql.auth.database | string | `"wxt"` | | -| postgresql.auth.enablePostgresUser | bool | `true` | | -| postgresql.auth.password | string | `""` | | -| postgresql.auth.postgresPassword | string | `""` | | -| postgresql.auth.username | string | `"wxt"` | | -| postgresql.enabled | bool | `false` | | -| postgresql.image.tag | string | `"14.3.0-debian-11-r3"` | | -| postgresql.primary.configuration | string | `"listen_addresses='*'\nmax_connections=200\nshared_buffers='512MB'\nwork_mem='2048MB'\neffective_cache_size='512MB'\nmaintenance_work_mem='32MB'\nmin_wal_size='512MB'\nmax_wal_size='512MB'\nwal_buffer='8048kB'\nbytea_output='escape'"` | | -| postgresql.primary.persistence.enabled | bool | `true` | | -| postgresql.primary.persistence.size | string | `"128Gi"` | | -| postgresql.volumePermissions.enabled | bool | `true` | | - -### PGBouncer - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| pgbouncer.enabled | bool | `false` | | -| pgbouncer.host | string | `"mypgserver.postgres.database.azure.com"` | | -| pgbouncer.maxClientConnections | int | `400` | | -| pgbouncer.password | string | `"password"` | | -| pgbouncer.poolSize | int | `50` | | -| pgbouncer.user | string | `"username@hostname"` | | - -## External - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| external.database | string | `"wetkit"` | | -| external.driver | string | `"mysql"` | | -| external.enabled | bool | `false` | | -| external.host | string | `"mysql.example.org"` | | -| external.password | string | `"password"` | | -| external.port | int | `3306` | | -| external.user | string | `"wetkit"` | | - -## Azure Files - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| azureFile.accessMode | string | `"ReadWriteMany"` | | -| azureFile.annotations | object | `{}` | | -| azureFile.enabled | bool | `false` | | -| azureFile.initMediaIconsFolder | bool | `true` | | -| azureFile.private.azureFile.readOnly | bool | `false` | | -| azureFile.private.azureFile.secretName | string | `"drupal-storage"` | | -| azureFile.private.azureFile.shareName | string | `"drupal-private"` | | -| azureFile.public.azureFile.readOnly | bool | `false` | | -| azureFile.public.azureFile.secretName | string | `"drupal-storage"` | | -| azureFile.public.azureFile.shareName | string | `"drupal-public"` | | -| azureFile.size | string | `"100Gi"` | | -| azureFile.storageClass | string | `"azurefile"` | | - -## Shared Disk - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| sharedDisk.accessMode | string | `"ReadWriteMany"` | | -| sharedDisk.annotations | object | `{}` | | -| sharedDisk.enabled | bool | `false` | | -| sharedDisk.initMediaIconsFolder | bool | `true` | | -| sharedDisk.maxShares | int | `2` | | -| sharedDisk.private.azureFile.readOnly | bool | `false` | | -| sharedDisk.private.azureFile.secretName | string | `"drupal-storage"` | | -| sharedDisk.private.azureFile.shareName | string | `"drupal-private"` | | -| sharedDisk.size | string | `"256Gi"` | | - -## Redis - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| redis.commonConfiguration | string | `"# Disable AOF https://redis.io/topics/persistence#append-only-file\nappendonly no\n# Disable RDB persistence.\nsave \"\""` | | -| redis.enabled | bool | `false` | | -| redis.master.disableCommands | list | `[]` | | -| redis.master.persistence.enabled | bool | `false` | | -| redis.master.service.type | string | `"ClusterIP"` | | -| redis.replica.disableCommands | list | `[]` | | -| redis.replica.enabled | bool | `false` | | -| redis.replica.persistence.enabled | bool | `false` | | -| redis.replica.replicaCount | int | `0` | | -| redis.replica.service.type | string | `"ClusterIP"` | | -| redis.sentinel.enabled | bool | `false` | | - -## Varnish - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| varnish.affinity | object | `{}` | | -| varnish.enabled | bool | `false` | | -| varnish.nodeSelector | object | `{}` | | -| varnish.resources | object | `{}` | | -| varnish.service.port | int | `80` | | -| varnish.service.type | string | `"ClusterIP"` | | -| varnish.tolerations | list | `[]` | | -| varnish.varnishConfigContent | string | `"vcl 4.0;\n\nimport std;\nimport directors;\n\nbackend nginx {\n .host = \"{{ include \"backend.fullname\" . }}-nginx\";\n .host_header = \"{{ include \"backend.fullname\" . }}-nginx\";\n .port = \"80\";\n}\n\nsub vcl_init {\n new backends = directors.round_robin();\n backends.add_backend(nginx);\n}\n\nsub vcl_recv {\n set req.http.X-Forwarded-Host = req.http.Host;\n if (!req.http.X-Forwarded-Proto) {\n set req.http.X-Forwarded-Proto = \"http\";\n }\n\n # Answer healthcheck\n if (req.url == \"/_healthcheck\" || req.url == \"/healthcheck.txt\") {\n return (synth(700, \"HEALTHCHECK\"));\n }\n set req.backend_hint = backends.backend();\n\n # Answer healthcheck\n if (req.url == \"/_healthcheck\" || req.url == \"/healthcheck.txt\") {\n return (synth(700, \"HEALTHCHECK\"));\n }\n set req.backend_hint = backends.backend();\n\n # Always cache certain file types\n # Remove cookies that Drupal doesn't care about\n if (req.url ~ \"(?i)\\.(asc|dat|tgz|png|gif|jpeg|jpg|ico|swf|css|js)(\\?.*)?$\") {\n unset req.http.Cookie;\n } else if (req.http.Cookie) {\n set req.http.Cookie = \";\" + req.http.Cookie;\n set req.http.Cookie = regsuball(req.http.Cookie, \"; +\", \";\");\n set req.http.Cookie = regsuball(req.http.Cookie, \";(SESS[a-z0-9]+|SSESS[a-z0-9]+|NO_CACHE)=\", \"; \\1=\");\n set req.http.Cookie = regsuball(req.http.Cookie, \";[^ ][^;]*\", \"\");\n set req.http.Cookie = regsuball(req.http.Cookie, \"^[; ]+|[; ]+$\", \"\");\n if (req.http.Cookie == \"\") {\n unset req.http.Cookie;\n } else {\n return (pass);\n }\n }\n # If POST, PUT or DELETE, then don't cache\n if (req.method == \"POST\" || req.method == \"PUT\" || req.method == \"DELETE\") {\n return (pass);\n }\n # Happens before we check if we have this in cache already.\n #\n # Typically you clean up the request here, removing cookies you don't need,\n # rewriting the request, etc.\n return (hash);\n #return (pass);\n}\n\nsub vcl_backend_fetch {\n # NEW\n set bereq.http.Host = \"{{ include \"backend.fullname\" . }}-nginx\";\n\n # Don't add 127.0.0.1 to X-Forwarded-For\n set bereq.http.X-Forwarded-For = regsub(bereq.http.X-Forwarded-For, \"(, )?127\\.0\\.0\\.1$\", \"\");\n}\n\nsub vcl_backend_response {\n if (beresp.http.Location) {\n set beresp.http.Location = regsub(\n beresp.http.Location,\n \"^https?://[^/]+/\",\n bereq.http.X-Forwarded-Proto + \"://\" + bereq.http.X-Forwarded-Host + \"/\"\n );\n }\n # Only cache select response codes\n if (beresp.status == 200 || beresp.status == 203 || beresp.status == 204 || beresp.status == 206 || beresp.status == 300 || beresp.status == 301 || beresp.status == 404 || beresp.status == 405 || beresp.status == 410 || beresp.status == 414 || beresp.status == 501) {\n # Cache for 5 minutes\n set beresp.ttl = 5m;\n set beresp.grace = 12h;\n set beresp.keep = 24h;\n } else {\n set beresp.ttl = 0s;\n }\n}\n\nsub vcl_deliver {\n # Remove identifying information\n unset resp.http.Server;\n unset resp.http.X-Powered-By;\n unset resp.http.X-Varnish;\n unset resp.http.Via;\n\n # Comment these for easier Drupal cache tag debugging in development.\n unset resp.http.Cache-Tags;\n unset resp.http.X-Drupal-Cache-Contexts;\n\n # Add Content-Security-Policy\n # set resp.http.Content-Security-Policy = \"default-src 'self' *.example.ca *.example.ca; style-src 'self' 'unsafe-inline' *.example.ca https://fonts.googleapis.com; script-src 'self' 'unsafe-inline' 'unsafe-eval' *.example.ca *.adobedtm.com use.fontawesome.com blob:; connect-src 'self' *.example.ca *.omtrdc.net *.demdex.net *.everesttech.net; img-src 'self' *.example.ca *.omtrdc.net *.demdex.net *.everesttech.net data:; font-src 'self' *.example.ca https://fonts.gstatic.com\";\n\n # Add CORS Headers\n # if (req.http.Origin ~ \"(?i)\\.example\\.ca$\") {\n # if (req.url ~ \"\\.(ttd|woff|woff2)(\\?.*)?$\") {\n # set resp.http.Access-Control-Allow-Origin = \"*\";\n # set resp.http.Access-Control-Allow-Methods = \"GET\";\n # }\n # }\n\n # Add X-Frame-Options\n if (req.url ~ \"^/livechat\" || req.url ~ \"^/(eng/|fra/)?media/\") {\n set resp.http.X-Frame-Options = \"SAMEORIGIN\";\n } else {\n set resp.http.X-Frame-Options = \"DENY\";\n }\n\n set resp.http.X-Content-Type-Options = \"nosniff\";\n set resp.http.X-XSS-Protection = \"1; mode=block\";\n\n # Happens when we have all the pieces we need, and are about to send the\n # response to the client.\n #\n # You can do accounting or modifying the final object here.\n if (obj.hits > 0) {\n set resp.http.X-Cache = \"HIT\";\n } else {\n set resp.http.X-Cache = \"MISS\";\n }\n # Handle errors\n if ( (resp.status >= 500 && resp.status <= 599)\n || resp.status == 400\n || resp.status == 401\n || resp.status == 403\n || resp.status == 404) {\n return (synth(resp.status));\n }\n}\n\nsub vcl_synth {\n # Remove identifying information\n unset resp.http.Server;\n unset resp.http.X-Powered-By;\n unset resp.http.X-Varnish;\n unset resp.http.Via;\n\n # Add Content-Security-Policy\n # set resp.http.Content-Security-Policy = \"default-src 'self' *.example.ca; style-src 'self' 'unsafe-inline' *.example.ca; script-src 'self' 'unsafe-inline' 'unsafe-eval' *.example.ca *.adobedtm.com use.fontawesome.com blob:; connect-src 'self' *.example.ca *.omtrdc.net *.demdex.net *.everesttech.net; img-src 'self' *.example.ca data:;\";\n # set resp.http.X-Content-Type-Options = \"nosniff\";\n # set resp.http.X-Frame-Options = \"DENY\";\n # set resp.http.X-XSS-Protection = \"1; mode=block\";\n\n # if (resp.status >= 500 && resp.status <= 599) {\n # set resp.http.Content-Type = \"text/html; charset=utf-8\";\n # synthetic(std.fileread(\"/data/configuration/varnish/errors/503.html\"));\n # return (deliver);\n # } elseif (resp.status == 400) { # 400 - Bad Request\n # set resp.http.Content-Type = \"text/html; charset=utf-8\";\n # synthetic(std.fileread(\"/data/configuration/varnish/errors/400.html\"));\n # return (deliver);\n # } elseif (resp.status == 401) { # 401 - Unauthorized\n # set resp.http.Content-Type = \"text/html; charset=utf-8\";\n # synthetic(std.fileread(\"/data/configuration/varnish/errors/401.html\"));\n # return (deliver);\n # } elseif (resp.status == 403) { # 403 - Forbidden\n # set resp.http.Content-Type = \"text/html; charset=utf-8\";\n # synthetic(std.fileread(\"/data/configuration/varnish/errors/403.html\"));\n # return (deliver);\n # } elseif (resp.status == 404) { # 404 - Not Found\n # set resp.http.Content-Type = \"text/html; charset=utf-8\";\n # synthetic(std.fileread(\"/data/configuration/varnish/errors/404.html\"));\n # return (deliver);\n # } else\n if (resp.status == 700) { # Respond to healthcheck\n set resp.status = 200;\n set resp.http.Content-Type = \"text/plain\";\n synthetic ( {\"OK\"} );\n return (deliver);\n }\n}\n\n##\n# ERROR HANDLING\n##\n# sub vcl_backend_error {\n# set beresp.http.Content-Type = \"text/html; charset=utf-8\";\n# synthetic(std.fileread(\"/data/configuration/varnish/errors/503.html\"));\n# return (deliver);\n# }\n"` | | -| varnish.varnishd.image | string | `"varnish"` | | -| varnish.varnishd.imagePullPolicy | string | `"IfNotPresent"` | | -| varnish.varnishd.tag | string | `"6.5.1"` | | - - - ----------------------------------------------- -Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/drupal7/README.md.gotmpl b/drupal7/README.md.gotmpl deleted file mode 100644 index 38ee7a64..00000000 --- a/drupal7/README.md.gotmpl +++ /dev/null @@ -1,166 +0,0 @@ -{{ template "chart.header" . }} - -{{ template "chart.deprecationWarning" . }} - -{{ template "chart.badgesSection" . }} - -{{ template "chart.description" . }} - -{{ template "chart.homepageLine" . }} - -{{ template "chart.maintainersSection" . }} - -{{ template "chart.sourcesSection" . }} - -{{ template "chart.requirementsSection" . }} - -## Prerequisites - -- Kubernetes 1.7+ -- Helm v3.0.0+ - -## Installing the Chart - -To install the chart with the release name `my-release`: - -```sh -helm repo add drupalwxt https://drupalwxt.github.io/helm-drupal -"drupalwxt" has been added to your repositories - -helm install my-release drupalwxt/drupal -NAME: my-release -``` - -Optionally you can git clone the helm chart and select the appropriate values file: - -```sh -git clone https://github.com/drupalwxt/helm-drupal -cd helm-drupal/drupal -cp values-azurefile.yaml values-override.yaml -helm install --name drupal -f values-override.yaml -``` - -## Ingress - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -{{- range .Values }} - {{- if hasPrefix "ingress." .Key }} -| {{ .Key }} | {{ .Type }} | {{ if .Default }}{{ .Default }}{{ else }}{{ .AutoDefault }}{{ end }} | {{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }} | - {{- end }} -{{- end }} - -## Drupal - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -{{- range .Values }} - {{- if hasPrefix "drupal." .Key }} -| {{ .Key }} | {{ .Type }} | {{ if .Default }}{{ .Default }}{{ else }}{{ .AutoDefault }}{{ end }} | {{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }} | - {{- end }} -{{- end }} - -## Nginx - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -{{- range .Values }} - {{- if hasPrefix "nginx." .Key }} -| {{ .Key }} | {{ .Type }} | {{ if .Default }}{{ .Default }}{{ else }}{{ .AutoDefault }}{{ end }} | {{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }} | - {{- end }} -{{- end }} - -## MySQL - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -{{- range .Values }} - {{- if hasPrefix "mysql." .Key }} -| {{ .Key }} | {{ .Type }} | {{ if .Default }}{{ .Default }}{{ else }}{{ .AutoDefault }}{{ end }} | {{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }} | - {{- end }} -{{- end }} - -### ProxySQL - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -{{- range .Values }} - {{- if hasPrefix "proxysql." .Key }} -| {{ .Key }} | {{ .Type }} | {{ if .Default }}{{ .Default }}{{ else }}{{ .AutoDefault }}{{ end }} | {{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }} | - {{- end }} -{{- end }} - -## PostgreSQL - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -{{- range .Values }} - {{- if hasPrefix "postgresql." .Key }} -| {{ .Key }} | {{ .Type }} | {{ if .Default }}{{ .Default }}{{ else }}{{ .AutoDefault }}{{ end }} | {{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }} | - {{- end }} -{{- end }} - -### PGBouncer - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -{{- range .Values }} - {{- if hasPrefix "pgbouncer." .Key }} -| {{ .Key }} | {{ .Type }} | {{ if .Default }}{{ .Default }}{{ else }}{{ .AutoDefault }}{{ end }} | {{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }} | - {{- end }} -{{- end }} - -## External - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -{{- range .Values }} - {{- if hasPrefix "external." .Key }} -| {{ .Key }} | {{ .Type }} | {{ if .Default }}{{ .Default }}{{ else }}{{ .AutoDefault }}{{ end }} | {{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }} | - {{- end }} -{{- end }} - -## Azure Files - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -{{- range .Values }} - {{- if hasPrefix "azureFile." .Key }} -| {{ .Key }} | {{ .Type }} | {{ if .Default }}{{ .Default }}{{ else }}{{ .AutoDefault }}{{ end }} | {{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }} | - {{- end }} -{{- end }} - -## Shared Disk - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -{{- range .Values }} - {{- if hasPrefix "sharedDisk." .Key }} -| {{ .Key }} | {{ .Type }} | {{ if .Default }}{{ .Default }}{{ else }}{{ .AutoDefault }}{{ end }} | {{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }} | - {{- end }} -{{- end }} - - -## Redis - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -{{- range .Values }} - {{- if hasPrefix "redis." .Key }} -| {{ .Key }} | {{ .Type }} | {{ if .Default }}{{ .Default }}{{ else }}{{ .AutoDefault }}{{ end }} | {{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }} | - {{- end }} -{{- end }} - -## Varnish - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -{{- range .Values }} - {{- if hasPrefix "varnish." .Key }} -| {{ .Key }} | {{ .Type }} | {{ if .Default }}{{ .Default }}{{ else }}{{ .AutoDefault }}{{ end }} | {{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }} | - {{- end }} -{{- end }} - - - -{{ template "helm-docs.versionFooter" . }} diff --git a/drupal7/charts/mysql-9.1.7.tgz b/drupal7/charts/mysql-9.1.7.tgz deleted file mode 100644 index 2c705d111021eb75fda76f7f2119ac631e0ad78e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44174 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 diff --git a/drupal7/charts/postgresql-11.6.6.tgz b/drupal7/charts/postgresql-11.6.6.tgz deleted file mode 100644 index b743d2ba20ddf1e4b0e2a5626965b170da2fee06..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56646 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 diff --git a/drupal7/charts/redis-16.13.2.tgz b/drupal7/charts/redis-16.13.2.tgz deleted file mode 100644 index 33b5e967b8cfff007e549c555cb64583606a7f91..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 88770 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 W&)~EBJ^wEN0RR6g?LxZ%rUw93uAxc* diff --git a/drupal7/charts/varnish-0.2.2.tgz b/drupal7/charts/varnish-0.2.2.tgz deleted file mode 100644 index b541c5b2c63e91e2617efeb6c2976ab904d7b66a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3538 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