diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fe69c692abc8c2d4882ea0cddc93bd2bbe34f4ee..bd1a297784a1a84cbfe7470dd83a7989646d32ed 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ include: - - project: 'platform-one/private/big-bang/pipeline-templates' + - project: 'platform-one/big-bang/pipeline-templates/pipeline-templates' ref: master - file: '/templates/generic-app.yml' + file: '/templates/package-tests.yml' diff --git a/CHANGELOG.md b/CHANGELOG.md index ea4d4ca00bc347ca4f1b8d00f4640b67fba24fb7..97a78d3ff4d475aef6a11fdc1b8d7e44173b6f67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## Initial Helm Chart Release - 2020-01-22 +Added SAML sso integration + +Added istio virtual service + +Modified images to use ironbank and repo1 + ## TechPreview0801 - 2020-08-01 Added enforced login/authentication diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index ce8eda04f97668a73de8a70a26505b9712e5b10a..0000000000000000000000000000000000000000 --- a/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM alpine AS fetcher - -RUN apk add wget - -WORKDIR /plugins - -# Fetch oidc plugin -RUN wget --quiet https://github.com/vaulttec/sonar-auth-oidc/releases/download/v2.0.0/sonar-auth-oidc-plugin-2.0.0.jar -RUN wget --quiet https://github.com/dependency-check/dependency-check-sonar-plugin/releases/download/1.2.6/sonar-dependency-check-plugin-1.2.6.jar -RUN wget --quiet https://github.com/SonarOpenCommunity/sonar-cxx/releases/download/cxx-1.3.2/sonar-c-plugin-1.3.2.1853.jar -RUN wget --quiet https://github.com/SonarOpenCommunity/sonar-cxx/releases/download/cxx-1.3.2/sonar-cxx-plugin-1.3.2.1853.jar -RUN ls -al - -# -FROM registry.dsop.io/platform-one/apps/sonarqube/sonarqube:8.3-community - -# Fetch plugins and load into appropriate dir -ENV PLUGIN_DIR=/opt/sonarqube/extensions/plugins - -# Fetch oidc plugin -COPY --from=fetcher /plugins/*.jar ${PLUGIN_DIR}/ diff --git a/chart/.helmignore b/chart/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..46fd89965620d5165dcd18d4873e7e9854d04a6d --- /dev/null +++ b/chart/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +# OWNERS file for Kubernetes +OWNERS diff --git a/chart/Chart.yaml b/chart/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..31a42e132a83b4e6e35e6d6433b74ce9e27329ec --- /dev/null +++ b/chart/Chart.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +appVersion: 8.6-community +name: sonarqube +description: SonarQube is an open sourced code quality scanning tool +version: 9.2.6-bb.0 +keywords: + - coverage + - security + - code + - quality +home: https://www.sonarqube.org/ +icon: https://www.sonarqube.org/assets/logo-31ad3115b1b4b120f3d1efd63e6b13ac9f1f89437f0cf6881cc4d8b5603a52b4.svg +sources: + - https://github.com/SonarSource/docker-sonarqube +maintainers: + - name: rjkernick + email: rjkernick@gmail.com + - name: tsiddique + email: tsiddique@live.com diff --git a/chart/LICENSE b/chart/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..c6782a577b00b06ce70b5cf24c3785d2f82246c2 --- /dev/null +++ b/chart/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Oteemo Inc + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/chart/README.md b/chart/README.md new file mode 100644 index 0000000000000000000000000000000000000000..4b9415feeb8cb033ad0bba2dd870042dc437c088 --- /dev/null +++ b/chart/README.md @@ -0,0 +1,248 @@ +# SonarQube + +[SonarQube](https://www.sonarqube.org/) is an open sourced code quality scanning tool. + +This chart was pulled from: https://github.com/Oteemo/charts/tree/master/charts/sonarqube + +## Introduction + +This chart bootstraps a SonarQube instance with a PostgreSQL database. + +## Prerequisites + +- Kubernetes 1.10+ + +## Installing the chart + +To install the chart: + +```bash +helm repo add oteemocharts https://oteemo.github.io/charts +helm install oteemocharts/sonarqube +``` +The above command deploys Sonarqube on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation. + +For OpenShift installations; if you wish for the chart to create the required SCC for the privileged initContainer, and run PostgreSQL under the restricted SCC use the following `set` statements: + +```bash +helm repo add oteemocharts https://oteemo.github.io/charts +helm install oteemocharts/sonarqube --set OpenShift.enabled=true,\ + serviceAccount.create=true,\ + postgresql.serviceAccount.enabled=true,\ + postgresql.securityContext.enabled=false,\ + postgresql.volumePermissions.enabled=true,\ + postgresql.volumePermissions.securityContext.runAsUser="auto" +``` + +The default login is admin/admin. + +## Uninstalling the chart + +To uninstall/delete the deployment: + +```bash +$ helm list +NAME REVISION UPDATED STATUS CHART NAMESPACE +kindly-newt 1 Mon Oct 2 15:05:44 2017 DEPLOYED sonarqube-0.1.0 default +$ helm delete kindly-newt +``` + +## Ingress Paths + +Some cloud may need the path to be /* instead of /. Try this first if you are having issues getting traffic through the ingress. + +## Configuration + +The following table lists the configurable parameters of the Sonarqube chart and their default values. + +| Parameter | Description | Default | +| ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | +| `replicaCount` | Number of replicas deployed | `1` | +| `deploymentStrategy` | Deployment strategy | `{}` | +| `priorityClassName` | Schedule pods on priority (commented out) | `"high-priority"` | +| `schedulerName` | Kubernetes scheduler name | None | +| `OpenShift.enabled` | Define if this deployment is for OpenShift | `false` | +| `OpenShift.createSCC` | If this deployment is for OpenShift, define if SCC should be created for sonarqube pod | `true` | +| `image.repository` | image repository | `sonarqube` | +| `image.tag` | `sonarqube` image tag. | `8.5.1-community` | +| `image.pullPolicy` | Image pull policy | `IfNotPresent` | +| `image.pullSecret` | imagePullSecret to use for private repository (commented out) | `my-repo-secret` | +| `securityContext.fsGroup` | Group applied to mounted directories/files | `1000` | +| `containerSecurityContext.runAsUser` | User to run containers in sonarqube pod as, unless overwritten (such as for init-sysctl container) | `1000` | +| `elasticsearch.configureNode` | [DEPRECATED] Use initSysctl.enabled instead. | `true` | +| `elasticsearch.bootstrapChecks` | Enables/disables Elasticsearch bootstrap checks | `true` | +| `service.type` | Kubernetes service type | `ClusterIP` | +| `service.externalPort` | Kubernetes service port | `9000` | +| `service.internalPort` | Kubernetes container port | `9000` | +| `service.labels` | Kubernetes service labels | None | +| `service.annotations` | Kubernetes service annotations | None | +| `service.loadBalancerSourceRanges` | Kubernetes service LB Allowed inbound IP addresses | None | +| `service.loadBalancerIP` | Kubernetes service LB Optional fixed external IP | None | +| `ingress.enabled` | Flag for enabling ingress | false | +| `ingress.labels` | Ingress additional labels | `{}` | +| `ingress.hosts[0].name` | Hostname to your SonarQube installation | `sonar.organization.com` | +| `ingress.hosts[0].path` | Path within the URL structure | / | +| `ingress.hosts[0].serviceName` | Optional field to override the default serviceName of a path | None | +| `ingress.hosts[0].servicePort` | Optional field to override the default servicePort of a path | None | +| `ingress.tls` | Ingress secrets for TLS certificates | `[]` | +| `affinity` | Node / Pod affinities | `{}` | +| `tolerations` | List of node taints to tolerate | `[]` | +| `nodeSelector` | Node labels for pod assignment | `{}` | +| `hostAliases` | Aliases for IPs in /etc/hosts | `[]` | +| `readinessProbe.initialDelaySecond` | ReadinessProbe initial delay for SonarQube checking | `60` | +| `readinessProbe.periodSeconds` | ReadinessProbe period between checking SonarQube | `30` | +| `readinessProbe.failureThreshold` | ReadinessProbe thresold for marking as failed | `6` | +| `readinessProbe.sonarWebContext` | SonarQube web context for readinessProbe | / | +| `livenessProbe.initialDelaySecond` | LivenessProbe initial delay for SonarQube checking | `60` | +| `livenessProbe.periodSeconds` | LivenessProbe period between checking SonarQube | `30` | +| `livenessProbe.sonarWebContext` | SonarQube web context for livenessProbe | / | +| `initContainers.image` | Change init container image | `busybox:1.32` | +| `initContainers.securityContext` | SecurityContext for init containers | `nil` | +| `initContainers.resources` | Resources for init containers | `{}` | +| `caCerts.image` | Change init CA certificates container image | `adoptopenjdk/openjdk11:alpine` | +| `caCerts.secret` | Name of the secret containing additional CA certificates | `nil` | +| `initSysctl.enabled` | Modify k8s worker to conform to system requirements | `true` | +| `initSysctl.vmMaxMapCount` | Set init sysctl container vm.max_map_count | `524288` | +| `initSysctl.fsFileMax` | Set init sysctl container fs.file-max | `131072` | +| `initSysctl.nofile` | Set init sysctl container open file descriptors limit | `131072` | +| `initSysctl.nproc` | Set init sysctl container open threads limit | `8192 ` | +| `initSysctl.image` | Change init sysctl container image | `busybox:1.32` | +| `initSysctl.securityContext` | InitSysctl container security context | `{privileged: true}` | +| `initSysctl.resources` | InitSysctl container resource requests & limits | `{}` | +| `plugins.install` | List of plugins to install | `[]` | +| `plugins.lib` | Plugins libray | `[]` | +| `plugins.resources` | Plugin Pod resource requests & limits | `{}` | +| `plugins.httpProxy` | For use behind a corporate proxy when downloading plugins | "" | +| `plugins.httpsProxy` | For use behind a corporate proxy when downloading plugins | "" | +| `plugins.noProxy` | For use behind a corporate proxy when downloading plugins | "" | +| `plugins.image` | Image for plugins container | "" | +| `plugins.resources` | Resources for plugins container | "" | +| `plugins.netrcCreds` | Name of the secret containing .netrc file to use creds when downloading plugins | "" | +| `jvmOpts` | Values to add to SONARQUBE_WEB_JVM_OPTS | `""` | +| `env` | Environment variables to attach to the pods | `nil` | +| `annotations` | Sonarqube Pod annotations | `{}` | +| `resources` | Sonarqube Pod resource requests & limits | `{}` | +| `persistence.enabled` | Flag for enabling persistent storage | false | +| `persistence.annotations` | Kubernetes pvc annotations | `{}` | +| `persistence.existingClaim` | Do not create a new PVC but use this one | None | +| `persistence.storageClass` | Storage class to be used | "" | +| `persistence.accessMode` | Volumes access mode to be set | `ReadWriteOnce` | +| `persistence.size` | Size of the volume | 10Gi | +| `persistence.volumes` | Specify extra volumes. Refer to ".spec.volumes" specification | [] | +| `persistence.mounts` | Specify extra mounts. Refer to ".spec.containers.volumeMounts" specification | [] | +| `emptyDir` | Configuration of resources for `emptyDir` | `{}` | +| `sonarProperties` | Custom `sonar.properties` file | None | +| `sonarSecretProperties` | Additional `sonar.properties` file to load from a secret | None | +| `sonarSecretKey` | Name of existing secret used for settings encryption | None | +| `jdbcDatabaseType` | Type of the JDBC Database driver | `postgreql` | +| `jdbcUrlOverride` | Overrides default JDBC URL creation | None | +| `postgresql.enabled` | Set to `false` to use external server | `true` | +| `postgresql.existingSecret` | Secret containing the password of the external Postgresql server | `null` | +| `postgresql.postgresqlServer` | Hostname of the external Postgresql server | `null` | +| `postgresql.postgresqlUsername` | Postgresql database user | `sonarUser` | +| `postgresql.postgresqlPassword` | Postgresql database password | `sonarPass` | +| `postgresql.postgresqlDatabase` | Postgresql database name | `sonarDB` | +| `postgresql.service.port` | Postgresql port | `5432` | +| `postgresql.resources.requests.memory`| Postgresql memory request | `256Mi` | +| `postgresql.resources.requests.cpu` | Postgresql cpu request | `250m` | +| `postgresql.resources.limits.memory` | Postgresql memory limit | `2Gi` | +| `postgresql.resources.limits.cpu` | Postgresql cpu limit | `2` | +| `postgresql.persistence.enabled` | Postgresql persistence en/disabled | `true` | +| `postgresql.persistence.accessMode` | Postgresql persistence accessMode | `ReadWriteOnce` | +| `postgresql.persistence.size` | Postgresql persistence size | `20Gi` | +| `postgresql.persistence.storageClass` | Postgresql persistence storageClass | `""` | +| `postgresql.securityContext.enabled` | Postgresql securityContext en/disabled | `true` | +| `postgresql.securityContext.fsGroup` | Postgresql securityContext fsGroup | `1001` | +| `postgresql.securityContext.runAsUser`| Postgresql securityContext runAsUser | `1001` | +| `postgresql.volumePermissions.enabled`| Postgres vol permissions en/disabled | `false` | +| `postgresql.volumePermissions.securityContext.runAsUser`| Postgres vol permissions secContext runAsUser | `0` | +| `postgresql.shmVolume.chmod.enabled` | Postgresql shared memory vol en/disabled | `false` | +| `postgresql.serivceAccount.enabled` | Postgresql service Account creation en/disabled | `false` | +| `postgresql.serivceAccount.name` | Postgresql service Account name (commented out) | `""` | +| `podLabels` | Map of labels to add to the pods | `{}` | +| `sonarqubeFolder` | Directory name of Sonarqube | `/opt/sonarqube` | +| `tests.enabled` | Flag that allows tests to be excluded from generated yaml | true | +| `tests.image` | Change init test container image | `dduportal/bats:0.4.0` | +| `serviceAccount.create` | If set to true, create a serviceAccount | false | +| `serviceAccount.name` | Name of the serviceAccount to create/use | `sonarqube-sonarqube` | +| `serviceAccount.annotations` | Additional serviceAccount annotations | `{}` | +| `extraConfig.secrets` | A list of `Secret`s (which must contain key/value pairs) which may be loaded into the Scanner as environment variables | `[]` | +| `extraConfig.configmaps` | A list of `ConfigMap`s (which must contain key/value pairs) which may be loaded into the Scanner as environment variables | `[]` | +| `account.adminPassword` | Custom admin password | `"admin"` | +| `account.currentAdminPassword` | Current admin password | `"admin"` | +| `curlContainerImage` | Curl container image | `"curlimages/curl:latest"` | +| `terminationGracePeriodSeconds` | Configuration of `terminationGracePeriodSeconds` | `60` | + +You can also configure values for the PostgreSQL database via the Postgresql [Chart](https://hub.helm.sh/charts/bitnami/postgresql) + +For overriding variables see: [Customizing the chart](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing) + +### Use custom `cacerts` + +In environments with air-gapped setup, especially with internal tooling (repos) and self-signed certificates it is required to provide an adequate `cacerts` which overrides the default one: + +1. Create a yaml file `cacerts.yaml` with a secret that contains one or more keys to represent the certificates that you want including + + ```yaml + apiVersion: v1 + kind: Secret + metadata: + name: my-cacerts + data: + cert-1.crt: | + xxxxxxxxxxxxxxxxxxxxxxx + ``` + +2. Upload your `cacerts.yaml` to a secret in the cluster you are installing Sonarqube to. + + ```shell + kubectl apply -f cacerts.yaml + ``` + +3. Set the following values of the chart: + + ```yaml + caCerts: + enabled: true + secret: my-cacerts + ``` + +### Elasticsearch Settings + +Since SonarQube comes bundled with an Elasticsearch instance, some [bootstrap checks](https://www.elastic.co/guide/en/elasticsearch/reference/master/bootstrap-checks.html) of the host settings are done at start. + +This chart offers the option to use an initContainer in privilaged mode to automatically set certain kernel settings on the kube worker. While this can ensure proper functionality of Elasticsearch, modifying the underlying kernel settings on the Kubernetes node can impact other users. It may be best to work with your cluster administrator to either provide specific nodes with the proper kernel settings, or ensure they are set cluster wide. + +To enable auto-configuration of the kube worker node, set `elasticsearch.configureNode` to `true`. This is the default behavior, so you do not need to explicitly set this. + +This will run `sysctl -w vm.max_map_count=262144` on the worker where the sonarqube pod(s) get scheduled. This needs to be set to `262144` but normally defaults to `65530`. Other kernel settings are recommended by the [docker image](https://hub.docker.com/_/sonarqube/#requirements), but the defaults work fine in most cases. + +To disable worker node configuration, set `elasticsearch.configureNode` to `false`. Note that if node configuration is not enabled, then you will likely need to also disable the Elasticsearch bootstrap checks. These can be explicitly disabled by setting `elasticsearch.bootstrapChecks` to `false`. + +### As of 7.9 Mysql is no longer supported, so it has been removed from the chart + +### Extra Config + +For environments where another tool, such as terraform or ansible, is used to provision infrastructure or passwords then setting databases addresses and credentials via helm becomes less than ideal. Ditto for environments where this config may be visible. + +In such environments, configuration may be read, via environment variables, from Secrets and ConfigMaps. + +1. Create a `ConfigMap` (or `Secret`) containing key/value pairs, as expected by Sonarqube + + ```yaml + apiVersion: v1 + kind: ConfigMap + metadata: + name: external-sonarqube-opts + data: + SONARQUBE_JDBC_USERNAME: foo + SONARQUBE_JDBC_URL: jdbc:postgresql://db.example.com:5432/sonar + ``` + +2. Set the following in your `values.yaml` (using the key `extraConfig.secrets` to reference `Secret`s) + + ```yaml + extraConfig: + configmaps: + - external-sonarqube-opts + ``` diff --git a/chart/charts/.gitkeep b/chart/charts/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/chart/charts/postgresql/.helmignore b/chart/charts/postgresql/.helmignore new file mode 100755 index 0000000000000000000000000000000000000000..f0c13194444163d1cba5c67d9e79231a62bc8f44 --- /dev/null +++ b/chart/charts/postgresql/.helmignore @@ -0,0 +1,21 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj diff --git a/chart/charts/postgresql/Chart.yaml b/chart/charts/postgresql/Chart.yaml new file mode 100755 index 0000000000000000000000000000000000000000..d63da83bca5dce1e47555fcbec413937d2890154 --- /dev/null +++ b/chart/charts/postgresql/Chart.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +appVersion: 11.7.0 +description: Chart for PostgreSQL, an object-relational database management system + (ORDBMS) with an emphasis on extensibility and on standards-compliance. +engine: gotpl +home: https://www.postgresql.org/ +icon: https://bitnami.com/assets/stacks/postgresql/img/postgresql-stack-110x117.png +keywords: +- postgresql +- postgres +- database +- sql +- replication +- cluster +maintainers: +- email: containers@bitnami.com + name: Bitnami +- email: cedric@desaintmartin.fr + name: desaintmartin +name: postgresql +sources: +- https://github.com/bitnami/bitnami-docker-postgresql +version: 8.6.4 diff --git a/chart/charts/postgresql/README.md b/chart/charts/postgresql/README.md new file mode 100755 index 0000000000000000000000000000000000000000..4a7c501d833ce70b8de9a2c49d7d1620c5b51c5b --- /dev/null +++ b/chart/charts/postgresql/README.md @@ -0,0 +1,567 @@ +# PostgreSQL + +[PostgreSQL](https://www.postgresql.org/) is an object-relational database management system (ORDBMS) with an emphasis on extensibility and on standards-compliance. + +For HA, please see [this repo](https://github.com/bitnami/charts/tree/master/bitnami/postgresql-ha) + +## TL;DR; + +```console +$ helm repo add bitnami https://charts.bitnami.com/bitnami +$ helm install my-release bitnami/postgresql +``` + +## Introduction + +This chart bootstraps a [PostgreSQL](https://github.com/bitnami/bitnami-docker-postgresql) deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.com/) for deployment and management of Helm Charts in clusters. This chart has been tested to work with NGINX Ingress, cert-manager, fluentd and Prometheus on top of the [BKPR](https://kubeprod.io/). + +## Prerequisites + +- Kubernetes 1.12+ +- Helm 2.11+ or Helm 3.0-beta3+ +- PV provisioner support in the underlying infrastructure + +## Installing the Chart +To install the chart with the release name `my-release`: + +```console +$ helm install my-release bitnami/postgresql +``` + +The command deploys PostgreSQL on the Kubernetes cluster in the default configuration. The [Parameters](#parameters) section lists the parameters that can be configured during installation. + +> **Tip**: List all releases using `helm list` + +## Uninstalling the Chart + +To uninstall/delete the `my-release` deployment: + +```console +$ helm delete my-release +``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. + +## Parameters + +The following tables lists the configurable parameters of the PostgreSQL chart and their default values. + +| Parameter | Description | Default | +|-----------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------| +| `global.imageRegistry` | Global Docker Image registry | `nil` | +| `global.postgresql.postgresqlDatabase` | PostgreSQL database (overrides `postgresqlDatabase`) | `nil` | +| `global.postgresql.postgresqlUsername` | PostgreSQL username (overrides `postgresqlUsername`) | `nil` | +| `global.postgresql.existingSecret` | Name of existing secret to use for PostgreSQL passwords (overrides `existingSecret`) | `nil` | +| `global.postgresql.postgresqlPassword` | PostgreSQL admin password (overrides `postgresqlPassword`) | `nil` | +| `global.postgresql.servicePort` | PostgreSQL port (overrides `service.port`) | `nil` | +| `global.postgresql.replicationPassword` | Replication user password (overrides `replication.password`) | `nil` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | +| `global.storageClass` | Global storage class for dynamic provisioning | `nil` | +| `image.registry` | PostgreSQL Image registry | `docker.io` | +| `image.repository` | PostgreSQL Image name | `bitnami/postgresql` | +| `image.tag` | PostgreSQL Image tag | `{TAG_NAME}` | +| `image.pullPolicy` | PostgreSQL Image pull policy | `IfNotPresent` | +| `image.pullSecrets` | Specify Image pull secrets | `nil` (does not add image pull secrets to deployed pods) | +| `image.debug` | Specify if debug values should be set | `false` | +| `nameOverride` | String to partially override postgresql.fullname template with a string (will prepend the release name) | `nil` | +| `fullnameOverride` | String to fully override postgresql.fullname template with a string | `nil` | +| `volumePermissions.enabled` | Enable init container that changes volume permissions in the data directory (for cases where the default k8s `runAsUser` and `fsUser` values do not work) | `false` | +| `volumePermissions.image.registry` | Init container volume-permissions image registry | `docker.io` | +| `volumePermissions.image.repository` | Init container volume-permissions image name | `bitnami/minideb` | +| `volumePermissions.image.tag` | Init container volume-permissions image tag | `buster` | +| `volumePermissions.image.pullPolicy` | Init container volume-permissions image pull policy | `Always` | +| `volumePermissions.securityContext.runAsUser` | User ID for the init container (when facing issues in OpenShift or uid unknown, try value "auto") | `0` | +| `usePasswordFile` | Have the secrets mounted as a file instead of env vars | `false` | +| `ldap.enabled` | Enable LDAP support | `false` | +| `ldap.existingSecret` | Name of existing secret to use for LDAP passwords | `nil` | +| `ldap.url` | LDAP URL beginning in the form `ldap[s]://host[:port]/basedn[?[attribute][?[scope][?[filter]]]]` | `nil` | +| `ldap.server` | IP address or name of the LDAP server. | `nil` | +| `ldap.port` | Port number on the LDAP server to connect to | `nil` | +| `ldap.scheme` | Set to `ldaps` to use LDAPS. | `nil` | +| `ldap.tls` | Set to `1` to use TLS encryption | `nil` | +| `ldap.prefix` | String to prepend to the user name when forming the DN to bind | `nil` | +| `ldap.suffix` | String to append to the user name when forming the DN to bind | `nil` | +| `ldap.search_attr` | Attribute to match agains the user name in the search | `nil` | +| `ldap.search_filter` | The search filter to use when doing search+bind authentication | `nil` | +| `ldap.baseDN` | Root DN to begin the search for the user in | `nil` | +| `ldap.bindDN` | DN of user to bind to LDAP | `nil` | +| `ldap.bind_password` | Password for the user to bind to LDAP | `nil` | +| `replication.enabled` | Enable replication | `false` | +| `replication.user` | Replication user | `repl_user` | +| `replication.password` | Replication user password | `repl_password` | +| `replication.slaveReplicas` | Number of slaves replicas | `1` | +| `replication.synchronousCommit` | Set synchronous commit mode. Allowed values: `on`, `remote_apply`, `remote_write`, `local` and `off` | `off` | +| `replication.numSynchronousReplicas` | Number of replicas that will have synchronous replication. Note: Cannot be greater than `replication.slaveReplicas`. | `0` | +| `replication.applicationName` | Cluster application name. Useful for advanced replication settings | `my_application` | +| `existingSecret` | Name of existing secret to use for PostgreSQL passwords. The secret has to contain the keys `postgresql-postgres-password` which is the password for `postgresqlUsername` when it is different of `postgres`, `postgresql-password` which will override `postgresqlPassword`, `postgresql-replication-password` which will override `replication.password` and `postgresql-ldap-password` which will be sed to authenticate on LDAP. | `nil` | +| `postgresqlPostgresPassword` | PostgreSQL admin password (used when `postgresqlUsername` is not `postgres`) | _random 10 character alphanumeric string_ | +| `postgresqlUsername` | PostgreSQL admin user | `postgres` | +| `postgresqlPassword` | PostgreSQL admin password | _random 10 character alphanumeric string_ | +| `postgresqlDatabase` | PostgreSQL database | `nil` | +| `postgresqlDataDir` | PostgreSQL data dir folder | `/bitnami/postgresql` (same value as persistence.mountPath) | +| `extraEnv` | Any extra environment variables you would like to pass on to the pod. The value is evaluated as a template. | `[]` | +| `extraEnvVarsCM` | Name of a Config Map containing extra environment variables you would like to pass on to the pod. | `nil` | +| `postgresqlInitdbArgs` | PostgreSQL initdb extra arguments | `nil` | +| `postgresqlInitdbWalDir` | PostgreSQL location for transaction log | `nil` | +| `postgresqlConfiguration` | Runtime Config Parameters | `nil` | +| `postgresqlExtendedConf` | Extended Runtime Config Parameters (appended to main or default configuration) | `nil` | +| `pgHbaConfiguration` | Content of pg_hba.conf | `nil (do not create pg_hba.conf)` | +| `configurationConfigMap` | ConfigMap with the PostgreSQL configuration files (Note: Overrides `postgresqlConfiguration` and `pgHbaConfiguration`). The value is evaluated as a template. | `nil` | +| `extendedConfConfigMap` | ConfigMap with the extended PostgreSQL configuration files. The value is evaluated as a template. | `nil` | +| `initdbScripts` | Dictionary of initdb scripts | `nil` | +| `initdbUsername` | PostgreSQL user to execute the .sql and sql.gz scripts | `nil` | +| `initdbPassword` | Password for the user specified in `initdbUsername` | `nil` | +| `initdbScriptsConfigMap` | ConfigMap with the initdb scripts (Note: Overrides `initdbScripts`). The value is evaluated as a template. | `nil` | +| `initdbScriptsSecret` | Secret with initdb scripts that contain sensitive information (Note: can be used with `initdbScriptsConfigMap` or `initdbScripts`). The value is evaluated as a template. | `nil` | +| `service.type` | Kubernetes Service type | `ClusterIP` | +| `service.port` | PostgreSQL port | `5432` | +| `service.nodePort` | Kubernetes Service nodePort | `nil` | +| `service.annotations` | Annotations for PostgreSQL service, the value is evaluated as a template. | {} | +| `service.loadBalancerIP` | loadBalancerIP if service type is `LoadBalancer` | `nil` | +| `service.loadBalancerSourceRanges` | Address that are allowed when svc is LoadBalancer | [] | +| `schedulerName` | Name of the k8s scheduler (other than default) | `nil` | +| `shmVolume.enabled` | Enable emptyDir volume for /dev/shm for master and slave(s) Pod(s) | `true` | +| `shmVolume.chmod.enabled` | Run at init chmod 777 of the /dev/shm (ignored if `volumePermissions.enabled` is `false`) | `true` | +| `persistence.enabled` | Enable persistence using PVC | `true` | +| `persistence.existingClaim` | Provide an existing `PersistentVolumeClaim`, the value is evaluated as a template. | `nil` | +| `persistence.mountPath` | Path to mount the volume at | `/bitnami/postgresql` | +| `persistence.subPath` | Subdirectory of the volume to mount at | `""` | +| `persistence.storageClass` | PVC Storage Class for PostgreSQL volume | `nil` | +| `persistence.accessModes` | PVC Access Mode for PostgreSQL volume | `[ReadWriteOnce]` | +| `persistence.size` | PVC Storage Request for PostgreSQL volume | `8Gi` | +| `persistence.annotations` | Annotations for the PVC | `{}` | +| `master.nodeSelector` | Node labels for pod assignment (postgresql master) | `{}` | +| `master.affinity` | Affinity labels for pod assignment (postgresql master) | `{}` | +| `master.tolerations` | Toleration labels for pod assignment (postgresql master) | `[]` | +| `master.anotations` | Map of annotations to add to the statefulset (postgresql master) | `{}` | +| `master.labels` | Map of labels to add to the statefulset (postgresql master) | `{}` | +| `master.podAnnotations` | Map of annotations to add to the pods (postgresql master) | `{}` | +| `master.podLabels` | Map of labels to add to the pods (postgresql master) | `{}` | +| `master.priorityClassName` | Priority Class to use for each pod (postgresql master) | `nil` | +| `master.extraInitContainers` | Additional init containers to add to the pods (postgresql master) | `[]` | +| `master.extraVolumeMounts` | Additional volume mounts to add to the pods (postgresql master) | `[]` | +| `master.extraVolumes` | Additional volumes to add to the pods (postgresql master) | `[]` | +| `master.sidecars` | Add additional containers to the pod | `[]` | +| `slave.nodeSelector` | Node labels for pod assignment (postgresql slave) | `{}` | +| `slave.affinity` | Affinity labels for pod assignment (postgresql slave) | `{}` | +| `slave.tolerations` | Toleration labels for pod assignment (postgresql slave) | `[]` | +| `slave.anotations` | Map of annotations to add to the statefulsets (postgresql slave) | `{}` | +| `slave.labels` | Map of labels to add to the statefulsets (postgresql slave) | `{}` | +| `slave.podAnnotations` | Map of annotations to add to the pods (postgresql slave) | `{}` | +| `slave.podLabels` | Map of labels to add to the pods (postgresql slave) | `{}` | +| `slave.priorityClassName` | Priority Class to use for each pod (postgresql slave) | `nil` | +| `slave.extraInitContainers` | Additional init containers to add to the pods (postgresql slave) | `[]` | +| `slave.extraVolumeMounts` | Additional volume mounts to add to the pods (postgresql slave) | `[]` | +| `slave.extraVolumes` | Additional volumes to add to the pods (postgresql slave) | `[]` | +| `slave.sidecars` | Add additional containers to the pod | `[]` | +| `terminationGracePeriodSeconds` | Seconds the pod needs to terminate gracefully | `nil` | +| `resources` | CPU/Memory resource requests/limits | Memory: `256Mi`, CPU: `250m` | +| `securityContext.enabled` | Enable security context | `true` | +| `securityContext.fsGroup` | Group ID for the container | `1001` | +| `securityContext.runAsUser` | User ID for the container | `1001` | +| `serviceAccount.enabled` | Enable service account (Note: Service Account will only be automatically created if `serviceAccount.name` is not set) | `false` | +| `serviceAcccount.name` | Name of existing service account | `nil` | +| `livenessProbe.enabled` | Would you like a livenessProbe to be enabled | `true` | +| `networkPolicy.enabled` | Enable NetworkPolicy | `false` | +| `networkPolicy.allowExternal` | Don't require client label for connections | `true` | +| `networkPolicy.explicitNamespacesSelector` | A Kubernetes LabelSelector to explicitly select namespaces from which ingress traffic could be allowed | `nil` | +| `livenessProbe.initialDelaySeconds` | Delay before liveness probe is initiated | 30 | +| `livenessProbe.periodSeconds` | How often to perform the probe | 10 | +| `livenessProbe.timeoutSeconds` | When the probe times out | 5 | +| `livenessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded. | 6 | +| `livenessProbe.successThreshold` | Minimum consecutive successes for the probe to be considered successful after having failed | 1 | +| `readinessProbe.enabled` | would you like a readinessProbe to be enabled | `true` | +| `readinessProbe.initialDelaySeconds` | Delay before readiness probe is initiated | 5 | +| `readinessProbe.periodSeconds` | How often to perform the probe | 10 | +| `readinessProbe.timeoutSeconds` | When the probe times out | 5 | +| `readinessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded. | 6 | +| `readinessProbe.successThreshold` | Minimum consecutive successes for the probe to be considered successful after having failed | 1 | +| `metrics.enabled` | Start a prometheus exporter | `false` | +| `metrics.service.type` | Kubernetes Service type | `ClusterIP` | +| `service.clusterIP` | Static clusterIP or None for headless services | `nil` | +| `metrics.service.annotations` | Additional annotations for metrics exporter pod | `{ prometheus.io/scrape: "true", prometheus.io/port: "9187"}` | +| `metrics.service.loadBalancerIP` | loadBalancerIP if redis metrics service type is `LoadBalancer` | `nil` | +| `metrics.serviceMonitor.enabled` | Set this to `true` to create ServiceMonitor for Prometheus operator | `false` | +| `metrics.serviceMonitor.additionalLabels` | Additional labels that can be used so ServiceMonitor will be discovered by Prometheus | `{}` | +| `metrics.serviceMonitor.namespace` | Optional namespace in which to create ServiceMonitor | `nil` | +| `metrics.serviceMonitor.interval` | Scrape interval. If not set, the Prometheus default scrape interval is used | `nil` | +| `metrics.serviceMonitor.scrapeTimeout` | Scrape timeout. If not set, the Prometheus default scrape timeout is used | `nil` | +| `metrics.prometheusRule.enabled` | Set this to true to create prometheusRules for Prometheus operator | `false` | +| `metrics.prometheusRule.additionalLabels` | Additional labels that can be used so prometheusRules will be discovered by Prometheus | `{}` | +| `metrics.prometheusRule.namespace` | namespace where prometheusRules resource should be created | the same namespace as postgresql | +| `metrics.prometheusRule.rules` | [rules](https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/) to be created, check values for an example. | `[]` | +| `metrics.image.registry` | PostgreSQL Image registry | `docker.io` | +| `metrics.image.repository` | PostgreSQL Image name | `bitnami/postgres-exporter` | +| `metrics.image.tag` | PostgreSQL Image tag | `{TAG_NAME}` | +| `metrics.image.pullPolicy` | PostgreSQL Image pull policy | `IfNotPresent` | +| `metrics.image.pullSecrets` | Specify Image pull secrets | `nil` (does not add image pull secrets to deployed pods) | +| `metrics.customMetrics` | Additional custom metrics | `nil` | +| `metrics.securityContext.enabled` | Enable security context for metrics | `false` | +| `metrics.securityContext.runAsUser` | User ID for the container for metrics | `1001` | +| `metrics.livenessProbe.initialDelaySeconds` | Delay before liveness probe is initiated | 30 | +| `metrics.livenessProbe.periodSeconds` | How often to perform the probe | 10 | +| `metrics.livenessProbe.timeoutSeconds` | When the probe times out | 5 | +| `metrics.livenessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded. | 6 | +| `metrics.livenessProbe.successThreshold` | Minimum consecutive successes for the probe to be considered successful after having failed | 1 | +| `metrics.readinessProbe.enabled` | would you like a readinessProbe to be enabled | `true` | +| `metrics.readinessProbe.initialDelaySeconds` | Delay before liveness probe is initiated | 5 | +| `metrics.readinessProbe.periodSeconds` | How often to perform the probe | 10 | +| `metrics.readinessProbe.timeoutSeconds` | When the probe times out | 5 | +| `metrics.readinessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded. | 6 | +| `metrics.readinessProbe.successThreshold` | Minimum consecutive successes for the probe to be considered successful after having failed | 1 | +| `updateStrategy` | Update strategy policy | `{type: "RollingUpdate"}` | + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +$ helm install my-release \ + --set postgresqlPassword=secretpassword,postgresqlDatabase=my-database \ + bitnami/postgresql +``` + +The above command sets the PostgreSQL `postgres` account password to `secretpassword`. Additionally it creates a database named `my-database`. + +Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, + +```console +$ helm install my-release -f values.yaml bitnami/postgresql +``` + +> **Tip**: You can use the default [values.yaml](values.yaml) + +## Configuration and installation details + +### [Rolling VS Immutable tags](https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/) + +It is strongly recommended to use immutable tags in a production environment. This ensures your deployment does not change automatically if the same tag is updated with a different image. + +Bitnami will release a new chart updating its containers if a new version of the main container, significant changes, or critical vulnerabilities exist. + +### Production configuration and horizontal scaling + +This chart includes a `values-production.yaml` file where you can find some parameters oriented to production configuration in comparison to the regular `values.yaml`. You can use this file instead of the default one. + +- Enable replication: +```diff +- replication.enabled: false ++ replication.enabled: true +``` + +- Number of slaves replicas: +```diff +- replication.slaveReplicas: 1 ++ replication.slaveReplicas: 2 +``` + +- Set synchronous commit mode: +```diff +- replication.synchronousCommit: "off" ++ replication.synchronousCommit: "on" +``` + +- Number of replicas that will have synchronous replication: +```diff +- replication.numSynchronousReplicas: 0 ++ replication.numSynchronousReplicas: 1 +``` + +- Start a prometheus exporter: +```diff +- metrics.enabled: false ++ metrics.enabled: true +``` + +To horizontally scale this chart, you can use the `--replicas` flag to modify the number of nodes in your PostgreSQL deployment. Also you can use the `values-production.yaml` file or modify the parameters shown above. + +### Change PostgreSQL version + +To modify the PostgreSQL version used in this chart you can specify a [valid image tag](https://hub.docker.com/r/bitnami/postgresql/tags/) using the `image.tag` parameter. For example, `image.tag=12.0.0` + +### postgresql.conf / pg_hba.conf files as configMap + +This helm chart also supports to customize the whole configuration file. + +Add your custom file to "files/postgresql.conf" in your working directory. This file will be mounted as configMap to the containers and it will be used for configuring the PostgreSQL server. + +Alternatively, you can specify PostgreSQL configuration parameters using the `postgresqlConfiguration` parameter as a dict, using camelCase, e.g. {"sharedBuffers": "500MB"}. + +In addition to these options, you can also set an external ConfigMap with all the configuration files. This is done by setting the `configurationConfigMap` parameter. Note that this will override the two previous options. + +### Allow settings to be loaded from files other than the default `postgresql.conf` + +If you don't want to provide the whole PostgreSQL configuration file and only specify certain parameters, you can add your extended `.conf` files to "files/conf.d/" in your working directory. +Those files will be mounted as configMap to the containers adding/overwriting the default configuration using the `include_dir` directive that allows settings to be loaded from files other than the default `postgresql.conf`. + +Alternatively, you can also set an external ConfigMap with all the extra configuration files. This is done by setting the `extendedConfConfigMap` parameter. Note that this will override the previous option. + +### Initialize a fresh instance + +The [Bitnami PostgreSQL](https://github.com/bitnami/bitnami-docker-postgresql) image allows you to use your custom scripts to initialize a fresh instance. In order to execute the scripts, they must be located inside the chart folder `files/docker-entrypoint-initdb.d` so they can be consumed as a ConfigMap. + +Alternatively, you can specify custom scripts using the `initdbScripts` parameter as dict. + +In addition to these options, you can also set an external ConfigMap with all the initialization scripts. This is done by setting the `initdbScriptsConfigMap` parameter. Note that this will override the two previous options. If your initialization scripts contain sensitive information such as credentials or passwords, you can use the `initdbScriptsSecret` parameter. + +The allowed extensions are `.sh`, `.sql` and `.sql.gz`. + +### Sidecars + +If you need additional containers to run within the same pod as PostgreSQL (e.g. an additional metrics or logging exporter), you can do so via the `sidecars` config parameter. Simply define your container according to the Kubernetes container spec. + +```yaml +# For the PostgreSQL master +master: + sidecars: + - name: your-image-name + image: your-image + imagePullPolicy: Always + ports: + - name: portname + containerPort: 1234 +# For the PostgreSQL replicas +slave: + sidecars: + - name: your-image-name + image: your-image + imagePullPolicy: Always + ports: + - name: portname + containerPort: 1234 +``` + +### Metrics + +The chart optionally can start a metrics exporter for [prometheus](https://prometheus.io). The metrics endpoint (port 9187) is not exposed and it is expected that the metrics are collected from inside the k8s cluster using something similar as the described in the [example Prometheus scrape configuration](https://github.com/prometheus/prometheus/blob/master/documentation/examples/prometheus-kubernetes.yml). + +The exporter allows to create custom metrics from additional SQL queries. See the Chart's `values.yaml` for an example and consult the [exporters documentation](https://github.com/wrouesnel/postgres_exporter#adding-new-metrics-via-a-config-file) for more details. + +### Use of global variables + +In more complex scenarios, we may have the following tree of dependencies + +``` + +--------------+ + | | + +------------+ Chart 1 +-----------+ + | | | | + | --------+------+ | + | | | + | | | + | | | + | | | + v v v ++-------+------+ +--------+------+ +--------+------+ +| | | | | | +| PostgreSQL | | Sub-chart 1 | | Sub-chart 2 | +| | | | | | ++--------------+ +---------------+ +---------------+ +``` + +The three charts below depend on the parent chart Chart 1. However, subcharts 1 and 2 may need to connect to PostgreSQL as well. In order to do so, subcharts 1 and 2 need to know the PostgreSQL credentials, so one option for deploying could be deploy Chart 1 with the following parameters: + +``` +postgresql.postgresqlPassword=testtest +subchart1.postgresql.postgresqlPassword=testtest +subchart2.postgresql.postgresqlPassword=testtest +postgresql.postgresqlDatabase=db1 +subchart1.postgresql.postgresqlDatabase=db1 +subchart2.postgresql.postgresqlDatabase=db1 +``` + +If the number of dependent sub-charts increases, installing the chart with parameters can become increasingly difficult. An alternative would be to set the credentials using global variables as follows: + +``` +global.postgresql.postgresqlPassword=testtest +global.postgresql.postgresqlDatabase=db1 +``` + +This way, the credentials will be available in all of the subcharts. + +## Persistence + +The [Bitnami PostgreSQL](https://github.com/bitnami/bitnami-docker-postgresql) image stores the PostgreSQL data and configurations at the `/bitnami/postgresql` path of the container. + +Persistent Volume Claims are used to keep the data across deployments. This is known to work in GCE, AWS, and minikube. +See the [Parameters](#parameters) section to configure the PVC or to disable persistence. + +If you already have data in it, you will fail to sync to standby nodes for all commits, details can refer to [code](https://github.com/bitnami/bitnami-docker-postgresql/blob/8725fe1d7d30ebe8d9a16e9175d05f7ad9260c93/9.6/debian-9/rootfs/libpostgresql.sh#L518-L556). If you need to use those data, please covert them to sql and import after `helm install` finished. + +## NetworkPolicy + +To enable network policy for PostgreSQL, install [a networking plugin that implements the Kubernetes NetworkPolicy spec](https://kubernetes.io/docs/tasks/administer-cluster/declare-network-policy#before-you-begin), and set `networkPolicy.enabled` to `true`. + +For Kubernetes v1.5 & v1.6, you must also turn on NetworkPolicy by setting the DefaultDeny namespace annotation. Note: this will enforce policy for _all_ pods in the namespace: + +```console +$ kubectl annotate namespace default "net.beta.kubernetes.io/network-policy={\"ingress\":{\"isolation\":\"DefaultDeny\"}}" +``` + +With NetworkPolicy enabled, traffic will be limited to just port 5432. + +For more precise policy, set `networkPolicy.allowExternal=false`. This will only allow pods with the generated client label to connect to PostgreSQL. +This label will be displayed in the output of a successful install. + +## Differences between Bitnami PostgreSQL image and [Docker Official](https://hub.docker.com/_/postgres) image + +- The Docker Official PostgreSQL image does not support replication. If you pass any replication environment variable, this would be ignored. The only environment variables supported by the Docker Official image are POSTGRES_USER, POSTGRES_DB, POSTGRES_PASSWORD, POSTGRES_INITDB_ARGS, POSTGRES_INITDB_WALDIR and PGDATA. All the remaining environment variables are specific to the Bitnami PostgreSQL image. +- The Bitnami PostgreSQL image is non-root by default. This requires that you run the pod with `securityContext` and updates the permissions of the volume with an `initContainer`. A key benefit of this configuration is that the pod follows security best practices and is prepared to run on Kubernetes distributions with hard security constraints like OpenShift. +- For OpenShift, one may either define the runAsUser and fsGroup accordingly, or try this more dynamic option: volumePermissions.securityContext.runAsUser="auto",securityContext.enabled=false,shmVolume.chmod.enabled=false + +### Deploy chart using Docker Official PostgreSQL Image + +From chart version 4.0.0, it is possible to use this chart with the Docker Official PostgreSQL image. +Besides specifying the new Docker repository and tag, it is important to modify the PostgreSQL data directory and volume mount point. Basically, the PostgreSQL data dir cannot be the mount point directly, it has to be a subdirectory. + +``` +helm install postgres \ + --set image.repository=postgres \ + --set image.tag=10.6 \ + --set postgresqlDataDir=/data/pgdata \ + --set persistence.mountPath=/data/ \ + bitnami/postgresql +``` + +## Upgrade + +It's necessary to specify the existing passwords while performing an upgrade to ensure the secrets are not updated with invalid randomly generated passwords. Remember to specify the existing values of the `postgresqlPassword` and `replication.password` parameters when upgrading the chart: + +```bash +$ helm upgrade my-release stable/postgresql \ + --set postgresqlPassword=[POSTGRESQL_PASSWORD] \ + --set replication.password=[REPLICATION_PASSWORD] +``` + +> Note: you need to substitute the placeholders _[POSTGRESQL_PASSWORD]_, and _[REPLICATION_PASSWORD]_ with the values obtained from instructions in the installation notes. + +## 8.0.0 + +Prefixes the port names with their protocols to comply with Istio conventions. + +If you depend on the port names in your setup, make sure to update them to reflect this change. + +## 7.1.0 + +Adds support for LDAP configuration. + +## 7.0.0 + +Helm performs a lookup for the object based on its group (apps), version (v1), and kind (Deployment). Also known as its GroupVersionKind, or GVK. Changing the GVK is considered a compatibility breaker from Kubernetes' point of view, so you cannot "upgrade" those objects to the new GVK in-place. Earlier versions of Helm 3 did not perform the lookup correctly which has since been fixed to match the spec. + +In https://github.com/helm/charts/pull/17281 the `apiVersion` of the statefulset resources was updated to `apps/v1` in tune with the api's deprecated, resulting in compatibility breakage. + +This major version bump signifies this change. + +## 6.5.7 + +In this version, the chart will use PostgreSQL with the Postgis extension included. The version used with Postgresql version 10, 11 and 12 is Postgis 2.5. It has been compiled with the following dependencies: + + - protobuf + - protobuf-c + - json-c + - geos + - proj + +## 5.0.0 + +In this version, the **chart is using PostgreSQL 11 instead of PostgreSQL 10**. You can find the main difference and notable changes in the following links: [https://www.postgresql.org/about/news/1894/](https://www.postgresql.org/about/news/1894/) and [https://www.postgresql.org/about/featurematrix/](https://www.postgresql.org/about/featurematrix/). + +For major releases of PostgreSQL, the internal data storage format is subject to change, thus complicating upgrades, you can see some errors like the following one in the logs: + +```bash +Welcome to the Bitnami postgresql container +Subscribe to project updates by watching https://github.com/bitnami/bitnami-docker-postgresql +Submit issues and feature requests at https://github.com/bitnami/bitnami-docker-postgresql/issues +Send us your feedback at containers@bitnami.com + +INFO ==> ** Starting PostgreSQL setup ** +NFO ==> Validating settings in POSTGRESQL_* env vars.. +INFO ==> Initializing PostgreSQL database... +INFO ==> postgresql.conf file not detected. Generating it... +INFO ==> pg_hba.conf file not detected. Generating it... +INFO ==> Deploying PostgreSQL with persisted data... +INFO ==> Configuring replication parameters +INFO ==> Loading custom scripts... +INFO ==> Enabling remote connections +INFO ==> Stopping PostgreSQL... +INFO ==> ** PostgreSQL setup finished! ** + +INFO ==> ** Starting PostgreSQL ** + [1] FATAL: database files are incompatible with server + [1] DETAIL: The data directory was initialized by PostgreSQL version 10, which is not compatible with this version 11.3. +``` +In this case, you should migrate the data from the old chart to the new one following an approach similar to that described in [this section](https://www.postgresql.org/docs/current/upgrading.html#UPGRADING-VIA-PGDUMPALL) from the official documentation. Basically, create a database dump in the old chart, move and restore it in the new one. + +### 4.0.0 + +This chart will use by default the Bitnami PostgreSQL container starting from version `10.7.0-r68`. This version moves the initialization logic from node.js to bash. This new version of the chart requires setting the `POSTGRES_PASSWORD` in the slaves as well, in order to properly configure the `pg_hba.conf` file. Users from previous versions of the chart are advised to upgrade immediately. + +IMPORTANT: If you do not want to upgrade the chart version then make sure you use the `10.7.0-r68` version of the container. Otherwise, you will get this error + +``` +The POSTGRESQL_PASSWORD environment variable is empty or not set. Set the environment variable ALLOW_EMPTY_PASSWORD=yes to allow the container to be started with blank passwords. This is recommended only for development +``` + +### 3.0.0 + +This releases make it possible to specify different nodeSelector, affinity and tolerations for master and slave pods. +It also fixes an issue with `postgresql.master.fullname` helper template not obeying fullnameOverride. + +#### Breaking changes + +- `affinty` has been renamed to `master.affinity` and `slave.affinity`. +- `tolerations` has been renamed to `master.tolerations` and `slave.tolerations`. +- `nodeSelector` has been renamed to `master.nodeSelector` and `slave.nodeSelector`. + +### 2.0.0 + +In order to upgrade from the `0.X.X` branch to `1.X.X`, you should follow the below steps: + + - Obtain the service name (`SERVICE_NAME`) and password (`OLD_PASSWORD`) of the existing postgresql chart. You can find the instructions to obtain the password in the NOTES.txt, the service name can be obtained by running + + ```console +$ kubectl get svc + ``` + +- Install (not upgrade) the new version + +```console +$ helm repo update +$ helm install my-release bitnami/postgresql +``` + +- Connect to the new pod (you can obtain the name by running `kubectl get pods`): + +```console +$ kubectl exec -it NAME bash +``` + +- Once logged in, create a dump file from the previous database using `pg_dump`, for that we should connect to the previous postgresql chart: + +```console +$ pg_dump -h SERVICE_NAME -U postgres DATABASE_NAME > /tmp/backup.sql +``` + +After run above command you should be prompted for a password, this password is the previous chart password (`OLD_PASSWORD`). +This operation could take some time depending on the database size. + +- Once you have the backup file, you can restore it with a command like the one below: + +```console +$ psql -U postgres DATABASE_NAME < /tmp/backup.sql +``` + +In this case, you are accessing to the local postgresql, so the password should be the new one (you can find it in NOTES.txt). + +If you want to restore the database and the database schema does not exist, it is necessary to first follow the steps described below. + +```console +$ psql -U postgres +postgres=# drop database DATABASE_NAME; +postgres=# create database DATABASE_NAME; +postgres=# create user USER_NAME; +postgres=# alter role USER_NAME with password 'BITNAMI_USER_PASSWORD'; +postgres=# grant all privileges on database DATABASE_NAME to USER_NAME; +postgres=# alter database DATABASE_NAME owner to USER_NAME; +``` diff --git a/chart/charts/postgresql/ci/default-values.yaml b/chart/charts/postgresql/ci/default-values.yaml new file mode 100755 index 0000000000000000000000000000000000000000..fc2ba605adaef469587377fc0574f0b4b938aa4d --- /dev/null +++ b/chart/charts/postgresql/ci/default-values.yaml @@ -0,0 +1 @@ +# Leave this file empty to ensure that CI runs builds against the default configuration in values.yaml. diff --git a/chart/charts/postgresql/ci/shmvolume-disabled-values.yaml b/chart/charts/postgresql/ci/shmvolume-disabled-values.yaml new file mode 100755 index 0000000000000000000000000000000000000000..347d3b40a8ea67a0d70bfa6b17821426d426c8fb --- /dev/null +++ b/chart/charts/postgresql/ci/shmvolume-disabled-values.yaml @@ -0,0 +1,2 @@ +shmVolume: + enabled: false diff --git a/chart/charts/postgresql/files/README.md b/chart/charts/postgresql/files/README.md new file mode 100755 index 0000000000000000000000000000000000000000..1813a2feaaf1a77b1b7cb37317c47e9b619d3a21 --- /dev/null +++ b/chart/charts/postgresql/files/README.md @@ -0,0 +1 @@ +Copy here your postgresql.conf and/or pg_hba.conf files to use it as a config map. diff --git a/chart/charts/postgresql/files/conf.d/README.md b/chart/charts/postgresql/files/conf.d/README.md new file mode 100755 index 0000000000000000000000000000000000000000..184c1875d575a262710552c0c7f97abbdb56a981 --- /dev/null +++ b/chart/charts/postgresql/files/conf.d/README.md @@ -0,0 +1,4 @@ +If you don't want to provide the whole configuration file and only specify certain parameters, you can copy here your extended `.conf` files. +These files will be injected as a config maps and add/overwrite the default configuration using the `include_dir` directive that allows settings to be loaded from files other than the default `postgresql.conf`. + +More info in the [bitnami-docker-postgresql README](https://github.com/bitnami/bitnami-docker-postgresql#configuration-file). diff --git a/chart/charts/postgresql/files/docker-entrypoint-initdb.d/README.md b/chart/charts/postgresql/files/docker-entrypoint-initdb.d/README.md new file mode 100755 index 0000000000000000000000000000000000000000..cba38091e0f45aac32fdd3bda933f547f95a9ea7 --- /dev/null +++ b/chart/charts/postgresql/files/docker-entrypoint-initdb.d/README.md @@ -0,0 +1,3 @@ +You can copy here your custom `.sh`, `.sql` or `.sql.gz` file so they are executed during the first boot of the image. + +More info in the [bitnami-docker-postgresql](https://github.com/bitnami/bitnami-docker-postgresql#initializing-a-new-instance) repository. \ No newline at end of file diff --git a/chart/charts/postgresql/templates/NOTES.txt b/chart/charts/postgresql/templates/NOTES.txt new file mode 100755 index 0000000000000000000000000000000000000000..3b5e6c60dfdaee174b8808e3b395150a1a1cce36 --- /dev/null +++ b/chart/charts/postgresql/templates/NOTES.txt @@ -0,0 +1,60 @@ +** Please be patient while the chart is being deployed ** + +PostgreSQL can be accessed via port {{ template "postgresql.port" . }} on the following DNS name from within your cluster: + + {{ template "postgresql.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local - Read/Write connection +{{- if .Values.replication.enabled }} + {{ template "postgresql.fullname" . }}-read.{{ .Release.Namespace }}.svc.cluster.local - Read only connection +{{- end }} + +{{- if and .Values.postgresqlPostgresPassword (not (eq .Values.postgresqlUsername "postgres")) }} + +To get the password for "postgres" run: + + export POSTGRES_ADMIN_PASSWORD=$(kubectl get secret --namespace {{ .Release.Namespace }} {{ template "postgresql.secretName" . }} -o jsonpath="{.data.postgresql-postgres-password}" | base64 --decode) +{{- end }} + +To get the password for "{{ template "postgresql.username" . }}" run: + + export POSTGRES_PASSWORD=$(kubectl get secret --namespace {{ .Release.Namespace }} {{ template "postgresql.secretName" . }} -o jsonpath="{.data.postgresql-password}" | base64 --decode) + +To connect to your database run the following command: + + kubectl run {{ template "postgresql.fullname" . }}-client --rm --tty -i --restart='Never' --namespace {{ .Release.Namespace }} --image {{ template "postgresql.image" . }} --env="PGPASSWORD=$POSTGRES_PASSWORD" {{- if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }} + --labels="{{ template "postgresql.fullname" . }}-client=true" {{- end }} --command -- psql --host {{ template "postgresql.fullname" . }} -U {{ .Values.postgresqlUsername }} -d {{- if .Values.postgresqlDatabase }} {{ .Values.postgresqlDatabase }}{{- else }} postgres{{- end }} -p {{ template "postgresql.port" . }} + +{{ if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }} +Note: Since NetworkPolicy is enabled, only pods with label {{ template "postgresql.fullname" . }}-client=true" will be able to connect to this PostgreSQL cluster. +{{- end }} + +To connect to your database from outside the cluster execute the following commands: + +{{- if contains "NodePort" .Values.service.type }} + + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "postgresql.fullname" . }}) + {{ if (include "postgresql.password" . ) }}PGPASSWORD="$POSTGRES_PASSWORD" {{ end }}psql --host $NODE_IP --port $NODE_PORT -U {{ .Values.postgresqlUsername }} -d {{- if .Values.postgresqlDatabase }} {{ .Values.postgresqlDatabase }}{{- else }} postgres{{- end }} + +{{- else if contains "LoadBalancer" .Values.service.type }} + + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "postgresql.fullname" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "postgresql.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + {{ if (include "postgresql.password" . ) }}PGPASSWORD="$POSTGRES_PASSWORD" {{ end }}psql --host $SERVICE_IP --port {{ template "postgresql.port" . }} -U {{ .Values.postgresqlUsername }} -d {{- if .Values.postgresqlDatabase }} {{ .Values.postgresqlDatabase }}{{- else }} postgres{{- end }} + +{{- else if contains "ClusterIP" .Values.service.type }} + + kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ template "postgresql.fullname" . }} {{ template "postgresql.port" . }}:{{ template "postgresql.port" . }} & + {{ if (include "postgresql.password" . ) }}PGPASSWORD="$POSTGRES_PASSWORD" {{ end }}psql --host 127.0.0.1 -U {{ .Values.postgresqlUsername }} -d {{- if .Values.postgresqlDatabase }} {{ .Values.postgresqlDatabase }}{{- else }} postgres{{- end }} -p {{ template "postgresql.port" . }} + +{{- end }} + +{{- include "postgresql.validateValues" . -}} + +{{- if and (contains "bitnami/" .Values.image.repository) (not (.Values.image.tag | toString | regexFind "-r\\d+$|sha256:")) }} + +WARNING: Rolling tag detected ({{ .Values.image.repository }}:{{ .Values.image.tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. ++info https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/ + +{{- end }} diff --git a/chart/charts/postgresql/templates/_helpers.tpl b/chart/charts/postgresql/templates/_helpers.tpl new file mode 100755 index 0000000000000000000000000000000000000000..3ee55726e7ddab8a3b25a2aff400d388eec03ceb --- /dev/null +++ b/chart/charts/postgresql/templates/_helpers.tpl @@ -0,0 +1,420 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "postgresql.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). +*/}} +{{- define "postgresql.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). +*/}} +{{- define "postgresql.master.fullname" -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- $fullname := default (printf "%s-%s" .Release.Name $name) .Values.fullnameOverride -}} +{{- if .Values.replication.enabled -}} +{{- printf "%s-%s" $fullname "master" | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s" $fullname | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "postgresql.networkPolicy.apiVersion" -}} +{{- if semverCompare ">=1.4-0, <1.7-0" .Capabilities.KubeVersion.GitVersion -}} +"extensions/v1beta1" +{{- else if semverCompare "^1.7-0" .Capabilities.KubeVersion.GitVersion -}} +"networking.k8s.io/v1" +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "postgresql.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Return the proper PostgreSQL image name +*/}} +{{- define "postgresql.image" -}} +{{- $registryName := .Values.image.registry -}} +{{- $repositoryName := .Values.image.repository -}} +{{- $tag := .Values.image.tag | toString -}} +{{/* +Helm 2.11 supports the assignment of a value to a variable defined in a different scope, +but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic. +Also, we can't use a single if because lazy evaluation is not an option +*/}} +{{- if .Values.global }} + {{- if .Values.global.imageRegistry }} + {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}} + {{- else -}} + {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} + {{- end -}} +{{- else -}} + {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} +{{- end -}} +{{- end -}} + +{{/* +Return PostgreSQL postgres user password +*/}} +{{- define "postgresql.postgres.password" -}} +{{- if .Values.global.postgresql.postgresqlPostgresPassword }} + {{- .Values.global.postgresql.postgresqlPostgresPassword -}} +{{- else if .Values.postgresqlPostgresPassword -}} + {{- .Values.postgresqlPostgresPassword -}} +{{- else -}} + {{- randAlphaNum 10 -}} +{{- end -}} +{{- end -}} + +{{/* +Return PostgreSQL password +*/}} +{{- define "postgresql.password" -}} +{{- if .Values.global.postgresql.postgresqlPassword }} + {{- .Values.global.postgresql.postgresqlPassword -}} +{{- else if .Values.postgresqlPassword -}} + {{- .Values.postgresqlPassword -}} +{{- else -}} + {{- randAlphaNum 10 -}} +{{- end -}} +{{- end -}} + +{{/* +Return PostgreSQL replication password +*/}} +{{- define "postgresql.replication.password" -}} +{{- if .Values.global.postgresql.replicationPassword }} + {{- .Values.global.postgresql.replicationPassword -}} +{{- else if .Values.replication.password -}} + {{- .Values.replication.password -}} +{{- else -}} + {{- randAlphaNum 10 -}} +{{- end -}} +{{- end -}} + +{{/* +Return PostgreSQL username +*/}} +{{- define "postgresql.username" -}} +{{- if .Values.global.postgresql.postgresqlUsername }} + {{- .Values.global.postgresql.postgresqlUsername -}} +{{- else -}} + {{- .Values.postgresqlUsername -}} +{{- end -}} +{{- end -}} + + +{{/* +Return PostgreSQL replication username +*/}} +{{- define "postgresql.replication.username" -}} +{{- if .Values.global.postgresql.replicationUser }} + {{- .Values.global.postgresql.replicationUser -}} +{{- else -}} + {{- .Values.replication.user -}} +{{- end -}} +{{- end -}} + +{{/* +Return PostgreSQL port +*/}} +{{- define "postgresql.port" -}} +{{- if .Values.global.postgresql.servicePort }} + {{- .Values.global.postgresql.servicePort -}} +{{- else -}} + {{- .Values.service.port -}} +{{- end -}} +{{- end -}} + +{{/* +Return PostgreSQL created database +*/}} +{{- define "postgresql.database" -}} +{{- if .Values.global.postgresql.postgresqlDatabase }} + {{- .Values.global.postgresql.postgresqlDatabase -}} +{{- else if .Values.postgresqlDatabase -}} + {{- .Values.postgresqlDatabase -}} +{{- end -}} +{{- end -}} + +{{/* +Return the proper image name to change the volume permissions +*/}} +{{- define "postgresql.volumePermissions.image" -}} +{{- $registryName := .Values.volumePermissions.image.registry -}} +{{- $repositoryName := .Values.volumePermissions.image.repository -}} +{{- $tag := .Values.volumePermissions.image.tag | toString -}} +{{/* +Helm 2.11 supports the assignment of a value to a variable defined in a different scope, +but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic. +Also, we can't use a single if because lazy evaluation is not an option +*/}} +{{- if .Values.global }} + {{- if .Values.global.imageRegistry }} + {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}} + {{- else -}} + {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} + {{- end -}} +{{- else -}} + {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} +{{- end -}} +{{- end -}} + +{{/* +Return the proper PostgreSQL metrics image name +*/}} +{{- define "postgresql.metrics.image" -}} +{{- $registryName := default "docker.io" .Values.metrics.image.registry -}} +{{- $repositoryName := .Values.metrics.image.repository -}} +{{- $tag := default "latest" .Values.metrics.image.tag | toString -}} +{{/* +Helm 2.11 supports the assignment of a value to a variable defined in a different scope, +but Helm 2.9 and 2.10 doesn't support it, so we need to implement this if-else logic. +Also, we can't use a single if because lazy evaluation is not an option +*/}} +{{- if .Values.global }} + {{- if .Values.global.imageRegistry }} + {{- printf "%s/%s:%s" .Values.global.imageRegistry $repositoryName $tag -}} + {{- else -}} + {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} + {{- end -}} +{{- else -}} + {{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} +{{- end -}} +{{- end -}} + +{{/* +Get the password secret. +*/}} +{{- define "postgresql.secretName" -}} +{{- if .Values.global.postgresql.existingSecret }} + {{- printf "%s" .Values.global.postgresql.existingSecret -}} +{{- else if .Values.existingSecret -}} + {{- printf "%s" .Values.existingSecret -}} +{{- else -}} + {{- printf "%s" (include "postgresql.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a secret object should be created +*/}} +{{- define "postgresql.createSecret" -}} +{{- if .Values.global.postgresql.existingSecret }} +{{- else if .Values.existingSecret -}} +{{- else -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Get the configuration ConfigMap name. +*/}} +{{- define "postgresql.configurationCM" -}} +{{- if .Values.configurationConfigMap -}} +{{- printf "%s" (tpl .Values.configurationConfigMap $) -}} +{{- else -}} +{{- printf "%s-configuration" (include "postgresql.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Get the extended configuration ConfigMap name. +*/}} +{{- define "postgresql.extendedConfigurationCM" -}} +{{- if .Values.extendedConfConfigMap -}} +{{- printf "%s" (tpl .Values.extendedConfConfigMap $) -}} +{{- else -}} +{{- printf "%s-extended-configuration" (include "postgresql.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Get the initialization scripts ConfigMap name. +*/}} +{{- define "postgresql.initdbScriptsCM" -}} +{{- if .Values.initdbScriptsConfigMap -}} +{{- printf "%s" (tpl .Values.initdbScriptsConfigMap $) -}} +{{- else -}} +{{- printf "%s-init-scripts" (include "postgresql.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Get the initialization scripts Secret name. +*/}} +{{- define "postgresql.initdbScriptsSecret" -}} +{{- printf "%s" (tpl .Values.initdbScriptsSecret $) -}} +{{- end -}} + +{{/* +Get the metrics ConfigMap name. +*/}} +{{- define "postgresql.metricsCM" -}} +{{- printf "%s-metrics" (include "postgresql.fullname" .) -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "postgresql.imagePullSecrets" -}} +{{/* +Helm 2.11 supports the assignment of a value to a variable defined in a different scope, +but Helm 2.9 and 2.10 does not support it, so we need to implement this if-else logic. +Also, we can not use a single if because lazy evaluation is not an option +*/}} +{{- if .Values.global }} +{{- if .Values.global.imagePullSecrets }} +imagePullSecrets: +{{- range .Values.global.imagePullSecrets }} + - name: {{ . }} +{{- end }} +{{- else if or .Values.image.pullSecrets .Values.metrics.image.pullSecrets .Values.volumePermissions.image.pullSecrets }} +imagePullSecrets: +{{- range .Values.image.pullSecrets }} + - name: {{ . }} +{{- end }} +{{- range .Values.metrics.image.pullSecrets }} + - name: {{ . }} +{{- end }} +{{- range .Values.volumePermissions.image.pullSecrets }} + - name: {{ . }} +{{- end }} +{{- end -}} +{{- else if or .Values.image.pullSecrets .Values.metrics.image.pullSecrets .Values.volumePermissions.image.pullSecrets }} +imagePullSecrets: +{{- range .Values.image.pullSecrets }} + - name: {{ . }} +{{- end }} +{{- range .Values.metrics.image.pullSecrets }} + - name: {{ . }} +{{- end }} +{{- range .Values.volumePermissions.image.pullSecrets }} + - name: {{ . }} +{{- end }} +{{- end -}} +{{- end -}} + +{{/* +Get the readiness probe command +*/}} +{{- define "postgresql.readinessProbeCommand" -}} +- | +{{- if (include "postgresql.database" .) }} + exec pg_isready -U {{ include "postgresql.username" . | quote }} -d {{ (include "postgresql.database" .) | quote }} -h 127.0.0.1 -p {{ template "postgresql.port" . }} +{{- else }} + exec pg_isready -U {{ include "postgresql.username" . | quote }} -h 127.0.0.1 -p {{ template "postgresql.port" . }} +{{- end }} +{{- if contains "bitnami/" .Values.image.repository }} + [ -f /opt/bitnami/postgresql/tmp/.initialized ] || [ -f /bitnami/postgresql/.initialized ] +{{- end -}} +{{- end -}} + +{{/* +Return the proper Storage Class +*/}} +{{- define "postgresql.storageClass" -}} +{{/* +Helm 2.11 supports the assignment of a value to a variable defined in a different scope, +but Helm 2.9 and 2.10 does not support it, so we need to implement this if-else logic. +*/}} +{{- if .Values.global -}} + {{- if .Values.global.storageClass -}} + {{- if (eq "-" .Values.global.storageClass) -}} + {{- printf "storageClassName: \"\"" -}} + {{- else }} + {{- printf "storageClassName: %s" .Values.global.storageClass -}} + {{- end -}} + {{- else -}} + {{- if .Values.persistence.storageClass -}} + {{- if (eq "-" .Values.persistence.storageClass) -}} + {{- printf "storageClassName: \"\"" -}} + {{- else }} + {{- printf "storageClassName: %s" .Values.persistence.storageClass -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- else -}} + {{- if .Values.persistence.storageClass -}} + {{- if (eq "-" .Values.persistence.storageClass) -}} + {{- printf "storageClassName: \"\"" -}} + {{- else }} + {{- printf "storageClassName: %s" .Values.persistence.storageClass -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Renders a value that contains template. +Usage: +{{ include "postgresql.tplValue" ( dict "value" .Values.path.to.the.Value "context" $) }} +*/}} +{{- define "postgresql.tplValue" -}} + {{- if typeIs "string" .value }} + {{- tpl .value .context }} + {{- else }} + {{- tpl (.value | toYaml) .context }} + {{- end }} +{{- end -}} + +{{/* +Return the appropriate apiVersion for statefulset. +*/}} +{{- define "postgresql.statefulset.apiVersion" -}} +{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "apps/v1beta2" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Compile all warnings into a single message, and call fail. +*/}} +{{- define "postgresql.validateValues" -}} +{{- $messages := list -}} +{{- $messages := append $messages (include "postgresql.validateValues.ldapConfigurationMethod" .) -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}} +{{- end -}} +{{- end -}} + +{{/* +Validate values of Postgresql - If ldap.url is used then you don't need the other settings for ldap +*/}} +{{- define "postgresql.validateValues.ldapConfigurationMethod" -}} +{{- if and .Values.ldap.enabled (and (not (empty .Values.ldap.url)) (not (empty .Values.ldap.server))) }} +postgresql: ldap.url, ldap.server + You cannot set both `ldap.url` and `ldap.server` at the same time. + Please provide a unique way to configure LDAP. + More info at https://www.postgresql.org/docs/current/auth-ldap.html +{{- end -}} +{{- end -}} diff --git a/chart/charts/postgresql/templates/configmap.yaml b/chart/charts/postgresql/templates/configmap.yaml new file mode 100755 index 0000000000000000000000000000000000000000..d2178c077e53a648cd47f3186e2cf8c683e1ed4d --- /dev/null +++ b/chart/charts/postgresql/templates/configmap.yaml @@ -0,0 +1,26 @@ +{{ if and (or (.Files.Glob "files/postgresql.conf") (.Files.Glob "files/pg_hba.conf") .Values.postgresqlConfiguration .Values.pgHbaConfiguration) (not .Values.configurationConfigMap) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "postgresql.fullname" . }}-configuration + labels: + app: {{ template "postgresql.name" . }} + chart: {{ template "postgresql.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} +data: +{{- if (.Files.Glob "files/postgresql.conf") }} +{{ (.Files.Glob "files/postgresql.conf").AsConfig | indent 2 }} +{{- else if .Values.postgresqlConfiguration }} + postgresql.conf: | +{{- range $key, $value := default dict .Values.postgresqlConfiguration }} + {{ $key | snakecase }}={{ $value }} +{{- end }} +{{- end }} +{{- if (.Files.Glob "files/pg_hba.conf") }} +{{ (.Files.Glob "files/pg_hba.conf").AsConfig | indent 2 }} +{{- else if .Values.pgHbaConfiguration }} + pg_hba.conf: | +{{ .Values.pgHbaConfiguration | indent 4 }} +{{- end }} +{{ end }} diff --git a/chart/charts/postgresql/templates/extended-config-configmap.yaml b/chart/charts/postgresql/templates/extended-config-configmap.yaml new file mode 100755 index 0000000000000000000000000000000000000000..8a4119578235f66f68bd1ee207baba13874a3d25 --- /dev/null +++ b/chart/charts/postgresql/templates/extended-config-configmap.yaml @@ -0,0 +1,21 @@ +{{- if and (or (.Files.Glob "files/conf.d/*.conf") .Values.postgresqlExtendedConf) (not .Values.extendedConfConfigMap)}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "postgresql.fullname" . }}-extended-configuration + labels: + app: {{ template "postgresql.name" . }} + chart: {{ template "postgresql.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} +data: +{{- with .Files.Glob "files/conf.d/*.conf" }} +{{ .AsConfig | indent 2 }} +{{- end }} +{{ with .Values.postgresqlExtendedConf }} + override.conf: | +{{- range $key, $value := . }} + {{ $key | snakecase }}={{ $value }} +{{- end }} +{{- end }} +{{- end }} diff --git a/chart/charts/postgresql/templates/initialization-configmap.yaml b/chart/charts/postgresql/templates/initialization-configmap.yaml new file mode 100755 index 0000000000000000000000000000000000000000..8eb5e05881f6d1f1eaeb9e0aa0135858745f65b2 --- /dev/null +++ b/chart/charts/postgresql/templates/initialization-configmap.yaml @@ -0,0 +1,24 @@ +{{- if and (or (.Files.Glob "files/docker-entrypoint-initdb.d/*.{sh,sql,sql.gz}") .Values.initdbScripts) (not .Values.initdbScriptsConfigMap) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "postgresql.fullname" . }}-init-scripts + labels: + app: {{ template "postgresql.name" . }} + chart: {{ template "postgresql.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} +{{- with .Files.Glob "files/docker-entrypoint-initdb.d/*.sql.gz" }} +binaryData: +{{- range $path, $bytes := . }} + {{ base $path }}: {{ $.Files.Get $path | b64enc | quote }} +{{- end }} +{{- end }} +data: +{{- with .Files.Glob "files/docker-entrypoint-initdb.d/*.{sh,sql}" }} +{{ .AsConfig | indent 2 }} +{{- end }} +{{- with .Values.initdbScripts }} +{{ toYaml . | indent 2 }} +{{- end }} +{{- end }} diff --git a/chart/charts/postgresql/templates/metrics-configmap.yaml b/chart/charts/postgresql/templates/metrics-configmap.yaml new file mode 100755 index 0000000000000000000000000000000000000000..524aa2f6a943a0b13c0f6a5f528137d6041557fd --- /dev/null +++ b/chart/charts/postgresql/templates/metrics-configmap.yaml @@ -0,0 +1,13 @@ +{{- if and .Values.metrics.enabled .Values.metrics.customMetrics }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "postgresql.metricsCM" . }} + labels: + app: {{ template "postgresql.name" . }} + chart: {{ template "postgresql.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} +data: + custom-metrics.yaml: {{ toYaml .Values.metrics.customMetrics | quote }} +{{- end }} diff --git a/chart/charts/postgresql/templates/metrics-svc.yaml b/chart/charts/postgresql/templates/metrics-svc.yaml new file mode 100755 index 0000000000000000000000000000000000000000..c610f09aff8dc06754370f5cf3f806336e4d2a4a --- /dev/null +++ b/chart/charts/postgresql/templates/metrics-svc.yaml @@ -0,0 +1,26 @@ +{{- if .Values.metrics.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "postgresql.fullname" . }}-metrics + labels: + app: {{ template "postgresql.name" . }} + chart: {{ template "postgresql.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} + annotations: +{{ toYaml .Values.metrics.service.annotations | indent 4 }} +spec: + type: {{ .Values.metrics.service.type }} + {{- if and (eq .Values.metrics.service.type "LoadBalancer") .Values.metrics.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.metrics.service.loadBalancerIP }} + {{- end }} + ports: + - name: http-metrics + port: 9187 + targetPort: http-metrics + selector: + app: {{ template "postgresql.name" . }} + release: {{ .Release.Name }} + role: master +{{- end }} diff --git a/chart/charts/postgresql/templates/networkpolicy.yaml b/chart/charts/postgresql/templates/networkpolicy.yaml new file mode 100755 index 0000000000000000000000000000000000000000..ea1fc9b3a2299850d223cb5344ee37e961a9881e --- /dev/null +++ b/chart/charts/postgresql/templates/networkpolicy.yaml @@ -0,0 +1,38 @@ +{{- if .Values.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ template "postgresql.networkPolicy.apiVersion" . }} +metadata: + name: {{ template "postgresql.fullname" . }} + labels: + app: {{ template "postgresql.name" . }} + chart: {{ template "postgresql.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} +spec: + podSelector: + matchLabels: + app: {{ template "postgresql.name" . }} + release: {{ .Release.Name | quote }} + ingress: + # Allow inbound connections + - ports: + - port: {{ template "postgresql.port" . }} + {{- if not .Values.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: + {{ template "postgresql.fullname" . }}-client: "true" + {{- if .Values.networkPolicy.explicitNamespacesSelector }} + namespaceSelector: +{{ toYaml .Values.networkPolicy.explicitNamespacesSelector | indent 12 }} + {{- end }} + - podSelector: + matchLabels: + app: {{ template "postgresql.name" . }} + release: {{ .Release.Name | quote }} + role: slave + {{- end }} + # Allow prometheus scrapes + - ports: + - port: 9187 +{{- end }} diff --git a/chart/charts/postgresql/templates/prometheusrule.yaml b/chart/charts/postgresql/templates/prometheusrule.yaml new file mode 100755 index 0000000000000000000000000000000000000000..44f1242dddb5f974dda7b49e4005c15949f5c8a8 --- /dev/null +++ b/chart/charts/postgresql/templates/prometheusrule.yaml @@ -0,0 +1,23 @@ +{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ template "postgresql.fullname" . }} +{{- with .Values.metrics.prometheusRule.namespace }} + namespace: {{ . }} +{{- end }} + labels: + app: {{ template "postgresql.name" . }} + chart: {{ template "postgresql.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} +{{- with .Values.metrics.prometheusRule.additionalLabels }} +{{ toYaml . | indent 4 }} +{{- end }} +spec: +{{- with .Values.metrics.prometheusRule.rules }} + groups: + - name: {{ template "postgresql.name" $ }} + rules: {{ tpl (toYaml .) $ | nindent 8 }} +{{- end }} +{{- end }} diff --git a/chart/charts/postgresql/templates/secrets.yaml b/chart/charts/postgresql/templates/secrets.yaml new file mode 100755 index 0000000000000000000000000000000000000000..094d18b49f8689b8e944541591cad96c6fe42752 --- /dev/null +++ b/chart/charts/postgresql/templates/secrets.yaml @@ -0,0 +1,23 @@ +{{- if (include "postgresql.createSecret" .) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "postgresql.fullname" . }} + labels: + app: {{ template "postgresql.name" . }} + chart: {{ template "postgresql.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} +type: Opaque +data: + {{- if and .Values.postgresqlPostgresPassword (not (eq .Values.postgresqlUsername "postgres")) }} + postgresql-postgres-password: {{ include "postgresql.postgres.password" . | b64enc | quote }} + {{- end }} + postgresql-password: {{ include "postgresql.password" . | b64enc | quote }} + {{- if .Values.replication.enabled }} + postgresql-replication-password: {{ include "postgresql.replication.password" . | b64enc | quote }} + {{- end }} + {{- if (and .Values.ldap.enabled .Values.ldap.bind_password)}} + postgresql-ldap-password: {{ .Values.ldap.bind_password | b64enc | quote }} + {{- end }} +{{- end -}} diff --git a/chart/charts/postgresql/templates/serviceaccount.yaml b/chart/charts/postgresql/templates/serviceaccount.yaml new file mode 100755 index 0000000000000000000000000000000000000000..27e5b516efa9c26e70d17098ba2ee8a869f10876 --- /dev/null +++ b/chart/charts/postgresql/templates/serviceaccount.yaml @@ -0,0 +1,11 @@ +{{- if and (.Values.serviceAccount.enabled) (not .Values.serviceAccount.name) }} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app: {{ template "postgresql.name" . }} + chart: {{ template "postgresql.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} + name: {{ template "postgresql.fullname" . }} +{{- end }} \ No newline at end of file diff --git a/chart/charts/postgresql/templates/servicemonitor.yaml b/chart/charts/postgresql/templates/servicemonitor.yaml new file mode 100755 index 0000000000000000000000000000000000000000..f3a529a964929fd03c73e0e426e59077e6e59ed9 --- /dev/null +++ b/chart/charts/postgresql/templates/servicemonitor.yaml @@ -0,0 +1,33 @@ +{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "postgresql.fullname" . }} + {{- if .Values.metrics.serviceMonitor.namespace }} + namespace: {{ .Values.metrics.serviceMonitor.namespace }} + {{- end }} + labels: + app: {{ template "postgresql.name" . }} + chart: {{ template "postgresql.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} + {{- if .Values.metrics.serviceMonitor.additionalLabels }} +{{ toYaml .Values.metrics.serviceMonitor.additionalLabels | indent 4 }} + {{- end }} +spec: + endpoints: + - port: http-metrics + {{- if .Values.metrics.serviceMonitor.interval }} + interval: {{ .Values.metrics.serviceMonitor.interval }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} + {{- end }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + app: {{ template "postgresql.name" . }} + release: {{ .Release.Name }} +{{- end }} diff --git a/chart/charts/postgresql/templates/statefulset-slaves.yaml b/chart/charts/postgresql/templates/statefulset-slaves.yaml new file mode 100755 index 0000000000000000000000000000000000000000..3290ff7fcd02ab861c9430e522be48758cd82f62 --- /dev/null +++ b/chart/charts/postgresql/templates/statefulset-slaves.yaml @@ -0,0 +1,299 @@ +{{- if .Values.replication.enabled }} +apiVersion: {{ template "postgresql.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: "{{ template "postgresql.fullname" . }}-slave" + labels: + app: {{ template "postgresql.name" . }} + chart: {{ template "postgresql.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} +{{- with .Values.slave.labels }} +{{ toYaml . | indent 4 }} +{{- end }} +{{- with .Values.slave.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + serviceName: {{ template "postgresql.fullname" . }}-headless + replicas: {{ .Values.replication.slaveReplicas }} + selector: + matchLabels: + app: {{ template "postgresql.name" . }} + release: {{ .Release.Name | quote }} + role: slave + template: + metadata: + name: {{ template "postgresql.fullname" . }} + labels: + app: {{ template "postgresql.name" . }} + chart: {{ template "postgresql.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} + role: slave +{{- with .Values.slave.podLabels }} +{{ toYaml . | indent 8 }} +{{- end }} +{{- with .Values.slave.podAnnotations }} + annotations: +{{ toYaml . | indent 8 }} +{{- end }} + spec: + {{- if .Values.schedulerName }} + schedulerName: "{{ .Values.schedulerName }}" + {{- end }} +{{- include "postgresql.imagePullSecrets" . | indent 6 }} + {{- if .Values.slave.nodeSelector }} + nodeSelector: +{{ toYaml .Values.slave.nodeSelector | indent 8 }} + {{- end }} + {{- if .Values.slave.affinity }} + affinity: +{{ toYaml .Values.slave.affinity | indent 8 }} + {{- end }} + {{- if .Values.slave.tolerations }} + tolerations: +{{ toYaml .Values.slave.tolerations | indent 8 }} + {{- end }} + {{- if .Values.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} + {{- end }} + {{- if .Values.securityContext.enabled }} + securityContext: + fsGroup: {{ .Values.securityContext.fsGroup }} + {{- end }} + {{- if .Values.serviceAccount.enabled }} + serviceAccountName: {{ default (include "postgresql.fullname" . ) .Values.serviceAccount.name}} + {{- end }} + {{- if or .Values.slave.extraInitContainers (and .Values.volumePermissions.enabled (or .Values.persistence.enabled (and .Values.shmVolume.enabled .Values.shmVolume.chmod.enabled))) }} + initContainers: + {{- if and .Values.volumePermissions.enabled (or .Values.persistence.enabled (and .Values.shmVolume.enabled .Values.shmVolume.chmod.enabled)) }} + - name: init-chmod-data + image: {{ template "postgresql.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + {{- if .Values.resources }} + resources: {{- toYaml .Values.resources | nindent 12 }} + {{- end }} + command: + - /bin/sh + - -cx + - | + {{ if .Values.persistence.enabled }} + mkdir -p {{ .Values.persistence.mountPath }}/data + chmod 700 {{ .Values.persistence.mountPath }}/data + find {{ .Values.persistence.mountPath }} -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | \ + {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} + xargs chown -R `id -u`:`id -G | cut -d " " -f2` + {{- else }} + xargs chown -R {{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} + {{- end }} + {{- end }} + {{- if and .Values.shmVolume.enabled .Values.shmVolume.chmod.enabled }} + chmod -R 777 /dev/shm + {{- end }} + {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} + securityContext: + {{- else }} + securityContext: + runAsUser: {{ .Values.volumePermissions.securityContext.runAsUser }} + {{- end }} + volumeMounts: + {{ if .Values.persistence.enabled }} + - name: data + mountPath: {{ .Values.persistence.mountPath }} + subPath: {{ .Values.persistence.subPath }} + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + mountPath: /dev/shm + {{- end }} + {{- end }} + {{- if .Values.slave.extraInitContainers }} +{{ tpl .Values.slave.extraInitContainers . | indent 8 }} + {{- end }} + {{- end }} + {{- if .Values.slave.priorityClassName }} + priorityClassName: {{ .Values.slave.priorityClassName }} + {{- end }} + containers: + - name: {{ template "postgresql.fullname" . }} + image: {{ template "postgresql.image" . }} + imagePullPolicy: "{{ .Values.image.pullPolicy }}" + {{- if .Values.resources }} + resources: {{- toYaml .Values.resources | nindent 12 }} + {{- end }} + {{- if .Values.securityContext.enabled }} + securityContext: + runAsUser: {{ .Values.securityContext.runAsUser }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" .Values.image.debug | quote }} + - name: POSTGRESQL_VOLUME_DIR + value: "{{ .Values.persistence.mountPath }}" + - name: POSTGRESQL_PORT_NUMBER + value: "{{ template "postgresql.port" . }}" + {{- if .Values.persistence.mountPath }} + - name: PGDATA + value: {{ .Values.postgresqlDataDir | quote }} + {{- end }} + - name: POSTGRES_REPLICATION_MODE + value: "slave" + - name: POSTGRES_REPLICATION_USER + value: {{ include "postgresql.replication.username" . | quote }} + {{- if .Values.usePasswordFile }} + - name: POSTGRES_REPLICATION_PASSWORD_FILE + value: "/opt/bitnami/postgresql/secrets/postgresql-replication-password" + {{- else }} + - name: POSTGRES_REPLICATION_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "postgresql.secretName" . }} + key: postgresql-replication-password + {{- end }} + - name: POSTGRES_CLUSTER_APP_NAME + value: {{ .Values.replication.applicationName }} + - name: POSTGRES_MASTER_HOST + value: {{ template "postgresql.fullname" . }} + - name: POSTGRES_MASTER_PORT_NUMBER + value: {{ include "postgresql.port" . | quote }} + {{- if and .Values.postgresqlPostgresPassword (not (eq .Values.postgresqlUsername "postgres")) }} + {{- if .Values.usePasswordFile }} + - name: POSTGRES_POSTGRES_PASSWORD_FILE + value: "/opt/bitnami/postgresql/secrets/postgresql-postgres-password" + {{- else }} + - name: POSTGRES_POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "postgresql.secretName" . }} + key: postgresql-postgres-password + {{- end }} + {{- end }} + {{- if .Values.usePasswordFile }} + - name: POSTGRES_PASSWORD_FILE + value: "/opt/bitnami/postgresql/secrets/postgresql-password" + {{- else }} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "postgresql.secretName" . }} + key: postgresql-password + {{- end }} + ports: + - name: tcp-postgresql + containerPort: {{ template "postgresql.port" . }} + {{- if .Values.livenessProbe.enabled }} + livenessProbe: + exec: + command: + - /bin/sh + - -c + {{- if (include "postgresql.database" .) }} + - exec pg_isready -U {{ include "postgresql.username" . | quote }} -d {{ (include "postgresql.database" .) | quote }} -h 127.0.0.1 -p {{ template "postgresql.port" . }} + {{- else }} + - exec pg_isready -U {{ include "postgresql.username" . | quote }} -h 127.0.0.1 -p {{ template "postgresql.port" . }} + {{- end }} + initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.readinessProbe.enabled }} + readinessProbe: + exec: + command: + - /bin/sh + - -c + - -e + {{- include "postgresql.readinessProbeCommand" . | nindent 16 }} + initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + {{- end }} + volumeMounts: + {{- if .Values.usePasswordFile }} + - name: postgresql-password + mountPath: /opt/bitnami/postgresql/secrets/ + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + mountPath: /dev/shm + {{- end }} + {{- if .Values.persistence.enabled }} + - name: data + mountPath: {{ .Values.persistence.mountPath }} + subPath: {{ .Values.persistence.subPath }} + {{ end }} + {{- if or (.Files.Glob "files/conf.d/*.conf") .Values.postgresqlExtendedConf .Values.extendedConfConfigMap }} + - name: postgresql-extended-config + mountPath: /bitnami/postgresql/conf/conf.d/ + {{- end }} + {{- if or (.Files.Glob "files/postgresql.conf") (.Files.Glob "files/pg_hba.conf") .Values.postgresqlConfiguration .Values.pgHbaConfiguration .Values.configurationConfigMap }} + - name: postgresql-config + mountPath: /bitnami/postgresql/conf + {{- end }} + {{- if .Values.slave.extraVolumeMounts }} + {{- toYaml .Values.slave.extraVolumeMounts | nindent 12 }} + {{- end }} +{{- if .Values.slave.sidecars }} +{{- include "postgresql.tplValue" ( dict "value" .Values.slave.sidecars "context" $ ) | nindent 8 }} +{{- end }} + volumes: + {{- if .Values.usePasswordFile }} + - name: postgresql-password + secret: + secretName: {{ template "postgresql.secretName" . }} + {{- end }} + {{- if or (.Files.Glob "files/postgresql.conf") (.Files.Glob "files/pg_hba.conf") .Values.postgresqlConfiguration .Values.pgHbaConfiguration .Values.configurationConfigMap}} + - name: postgresql-config + configMap: + name: {{ template "postgresql.configurationCM" . }} + {{- end }} + {{- if or (.Files.Glob "files/conf.d/*.conf") .Values.postgresqlExtendedConf .Values.extendedConfConfigMap }} + - name: postgresql-extended-config + configMap: + name: {{ template "postgresql.extendedConfigurationCM" . }} + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + emptyDir: + medium: Memory + sizeLimit: 1Gi + {{- end }} + {{- if not .Values.persistence.enabled }} + - name: data + emptyDir: {} + {{- end }} + {{- if .Values.slave.extraVolumes }} + {{- toYaml .Values.slave.extraVolumes | nindent 8 }} + {{- end }} + updateStrategy: + type: {{ .Values.updateStrategy.type }} + {{- if (eq "Recreate" .Values.updateStrategy.type) }} + rollingUpdate: null + {{- end }} +{{- if .Values.persistence.enabled }} + volumeClaimTemplates: + - metadata: + name: data + {{- with .Values.persistence.annotations }} + annotations: + {{- range $key, $value := . }} + {{ $key }}: {{ $value }} + {{- end }} + {{- end }} + spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{ include "postgresql.storageClass" . }} +{{- end }} +{{- end }} diff --git a/chart/charts/postgresql/templates/statefulset.yaml b/chart/charts/postgresql/templates/statefulset.yaml new file mode 100755 index 0000000000000000000000000000000000000000..3390be22b2bb94fc3ea72a20384bb929d568cb56 --- /dev/null +++ b/chart/charts/postgresql/templates/statefulset.yaml @@ -0,0 +1,458 @@ +apiVersion: {{ template "postgresql.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ template "postgresql.master.fullname" . }} + labels: + app: {{ template "postgresql.name" . }} + chart: {{ template "postgresql.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} +{{- with .Values.master.labels }} +{{ toYaml . | indent 4 }} +{{- end }} +{{- with .Values.master.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + serviceName: {{ template "postgresql.fullname" . }}-headless + replicas: 1 + updateStrategy: + type: {{ .Values.updateStrategy.type }} + {{- if (eq "Recreate" .Values.updateStrategy.type) }} + rollingUpdate: null + {{- end }} + selector: + matchLabels: + app: {{ template "postgresql.name" . }} + release: {{ .Release.Name | quote }} + role: master + template: + metadata: + name: {{ template "postgresql.fullname" . }} + labels: + app: {{ template "postgresql.name" . }} + chart: {{ template "postgresql.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} + role: master +{{- with .Values.master.podLabels }} +{{ toYaml . | indent 8 }} +{{- end }} +{{- with .Values.master.podAnnotations }} + annotations: +{{ toYaml . | indent 8 }} +{{- end }} + spec: + {{- if .Values.schedulerName }} + schedulerName: "{{ .Values.schedulerName }}" + {{- end }} +{{- include "postgresql.imagePullSecrets" . | indent 6 }} + {{- if .Values.master.nodeSelector }} + nodeSelector: +{{ toYaml .Values.master.nodeSelector | indent 8 }} + {{- end }} + {{- if .Values.master.affinity }} + affinity: +{{ toYaml .Values.master.affinity | indent 8 }} + {{- end }} + {{- if .Values.master.tolerations }} + tolerations: +{{ toYaml .Values.master.tolerations | indent 8 }} + {{- end }} + {{- if .Values.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} + {{- end }} + {{- if .Values.securityContext.enabled }} + securityContext: + fsGroup: {{ .Values.securityContext.fsGroup }} + {{- end }} + {{- if .Values.serviceAccount.enabled }} + serviceAccountName: {{ default (include "postgresql.fullname" . ) .Values.serviceAccount.name }} + {{- end }} + {{- if or .Values.master.extraInitContainers (and .Values.volumePermissions.enabled (or .Values.persistence.enabled (and .Values.shmVolume.enabled .Values.shmVolume.chmod.enabled))) }} + initContainers: + {{- if and .Values.volumePermissions.enabled (or .Values.persistence.enabled (and .Values.shmVolume.enabled .Values.shmVolume.chmod.enabled)) }} + - name: init-chmod-data + image: {{ template "postgresql.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + {{- if .Values.resources }} + resources: {{- toYaml .Values.resources | nindent 12 }} + {{- end }} + command: + - /bin/sh + - -cx + - | + {{ if .Values.persistence.enabled }} + mkdir -p {{ .Values.persistence.mountPath }}/data + chmod 700 {{ .Values.persistence.mountPath }}/data + find {{ .Values.persistence.mountPath }} -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | \ + {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} + xargs chown -R `id -u`:`id -G | cut -d " " -f2` + {{- else }} + xargs chown -R {{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} + {{- end }} + {{- end }} + {{- if and .Values.shmVolume.enabled .Values.shmVolume.chmod.enabled }} + chmod -R 777 /dev/shm + {{- end }} + {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} + securityContext: + {{- else }} + securityContext: + runAsUser: {{ .Values.volumePermissions.securityContext.runAsUser }} + {{- end }} + volumeMounts: + {{ if .Values.persistence.enabled }} + - name: data + mountPath: {{ .Values.persistence.mountPath }} + subPath: {{ .Values.persistence.subPath }} + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + mountPath: /dev/shm + {{- end }} + {{- end }} + {{- if .Values.master.extraInitContainers }} +{{ tpl .Values.master.extraInitContainers . | indent 8 }} + {{- end }} + {{- end }} + {{- if .Values.master.priorityClassName }} + priorityClassName: {{ .Values.master.priorityClassName }} + {{- end }} + containers: + - name: {{ template "postgresql.fullname" . }} + image: {{ template "postgresql.image" . }} + imagePullPolicy: "{{ .Values.image.pullPolicy }}" + {{- if .Values.resources }} + resources: {{- toYaml .Values.resources | nindent 12 }} + {{- end }} + {{- if .Values.securityContext.enabled }} + securityContext: + runAsUser: {{ .Values.securityContext.runAsUser }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" .Values.image.debug | quote }} + - name: POSTGRESQL_PORT_NUMBER + value: "{{ template "postgresql.port" . }}" + - name: POSTGRESQL_VOLUME_DIR + value: "{{ .Values.persistence.mountPath }}" + {{- if .Values.postgresqlInitdbArgs }} + - name: POSTGRES_INITDB_ARGS + value: {{ .Values.postgresqlInitdbArgs | quote }} + {{- end }} + {{- if .Values.postgresqlInitdbWalDir }} + - name: POSTGRES_INITDB_WALDIR + value: {{ .Values.postgresqlInitdbWalDir | quote }} + {{- end }} + {{- if .Values.initdbUser }} + - name: POSTGRESQL_INITSCRIPTS_USERNAME + value: {{ .Values.initdbUser }} + {{- end }} + {{- if .Values.initdbPassword }} + - name: POSTGRESQL_INITSCRIPTS_PASSWORD + value: .Values.initdbPassword + {{- end }} + {{- if .Values.persistence.mountPath }} + - name: PGDATA + value: {{ .Values.postgresqlDataDir | quote }} + {{- end }} + {{- if .Values.replication.enabled }} + - name: POSTGRES_REPLICATION_MODE + value: "master" + - name: POSTGRES_REPLICATION_USER + value: {{ include "postgresql.replication.username" . | quote }} + {{- if .Values.usePasswordFile }} + - name: POSTGRES_REPLICATION_PASSWORD_FILE + value: "/opt/bitnami/postgresql/secrets/postgresql-replication-password" + {{- else }} + - name: POSTGRES_REPLICATION_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "postgresql.secretName" . }} + key: postgresql-replication-password + {{- end }} + {{- if not (eq .Values.replication.synchronousCommit "off")}} + - name: POSTGRES_SYNCHRONOUS_COMMIT_MODE + value: {{ .Values.replication.synchronousCommit | quote }} + - name: POSTGRES_NUM_SYNCHRONOUS_REPLICAS + value: {{ .Values.replication.numSynchronousReplicas | quote }} + {{- end }} + - name: POSTGRES_CLUSTER_APP_NAME + value: {{ .Values.replication.applicationName }} + {{- end }} + {{- if and .Values.postgresqlPostgresPassword (not (eq .Values.postgresqlUsername "postgres")) }} + {{- if .Values.usePasswordFile }} + - name: POSTGRES_POSTGRES_PASSWORD_FILE + value: "/opt/bitnami/postgresql/secrets/postgresql-postgres-password" + {{- else }} + - name: POSTGRES_POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "postgresql.secretName" . }} + key: postgresql-postgres-password + {{- end }} + {{- end }} + - name: POSTGRES_USER + value: {{ include "postgresql.username" . | quote }} + {{- if .Values.usePasswordFile }} + - name: POSTGRES_PASSWORD_FILE + value: "/opt/bitnami/postgresql/secrets/postgresql-password" + {{- else }} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "postgresql.secretName" . }} + key: postgresql-password + {{- end }} + {{- if (include "postgresql.database" .) }} + - name: POSTGRES_DB + value: {{ (include "postgresql.database" .) | quote }} + {{- end }} + {{- if .Values.extraEnv }} + {{- include "postgresql.tplValue" (dict "value" .Values.extraEnv "context" $) | nindent 12 }} + {{- end }} + - name: POSTGRESQL_ENABLE_LDAP + value: {{ ternary "yes" "no" .Values.ldap.enabled | quote }} + {{- if .Values.ldap.enabled }} + - name: POSTGRESQL_LDAP_SERVER + value: {{ .Values.ldap.server }} + - name: POSTGRESQL_LDAP_PORT + value: {{ .Values.ldap.port | quote }} + - name: POSTGRESQL_LDAP_SCHEME + value: {{ .Values.ldap.scheme }} + {{- if .Values.ldap.tls }} + - name: POSTGRESQL_LDAP_TLS + value: "1" + {{- end}} + - name: POSTGRESQL_LDAP_PREFIX + value: {{ .Values.ldap.prefix | quote }} + - name: POSTGRESQL_LDAP_SUFFIX + value: {{ .Values.ldap.suffix | quote}} + - name: POSTGRESQL_LDAP_BASE_DN + value: {{ .Values.ldap.baseDN }} + - name: POSTGRESQL_LDAP_BIND_DN + value: {{ .Values.ldap.bindDN }} + {{- if (not (empty .Values.ldap.bind_password)) }} + - name: POSTGRESQL_LDAP_BIND_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "postgresql.secretName" . }} + key: postgresql-ldap-password + {{- end}} + - name: POSTGRESQL_LDAP_SEARCH_ATTR + value: {{ .Values.ldap.search_attr }} + - name: POSTGRESQL_LDAP_SEARCH_FILTER + value: {{ .Values.ldap.search_filter }} + - name: POSTGRESQL_LDAP_URL + value: {{ .Values.ldap.url }} + {{- end}} + {{- if .Values.extraEnvVarsCM }} + envFrom: + - configMapRef: + name: {{ .Values.extraEnvVarsCM }} + {{- end }} + ports: + - name: tcp-postgresql + containerPort: {{ template "postgresql.port" . }} + {{- if .Values.livenessProbe.enabled }} + livenessProbe: + exec: + command: + - /bin/sh + - -c + {{- if (include "postgresql.database" .) }} + - exec pg_isready -U {{ include "postgresql.username" . | quote }} -d {{ (include "postgresql.database" .) | quote }} -h 127.0.0.1 -p {{ template "postgresql.port" . }} + {{- else }} + - exec pg_isready -U {{ include "postgresql.username" . | quote }} -h 127.0.0.1 -p {{ template "postgresql.port" . }} + {{- end }} + initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.readinessProbe.enabled }} + readinessProbe: + exec: + command: + - /bin/sh + - -c + - -e + {{- include "postgresql.readinessProbeCommand" . | nindent 16 }} + initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + {{- end }} + volumeMounts: + {{- if or (.Files.Glob "files/docker-entrypoint-initdb.d/*.{sh,sql,sql.gz}") .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + mountPath: /docker-entrypoint-initdb.d/ + {{- end }} + {{- if .Values.initdbScriptsSecret }} + - name: custom-init-scripts-secret + mountPath: /docker-entrypoint-initdb.d/secret + {{- end }} + {{- if or (.Files.Glob "files/conf.d/*.conf") .Values.postgresqlExtendedConf .Values.extendedConfConfigMap }} + - name: postgresql-extended-config + mountPath: /bitnami/postgresql/conf/conf.d/ + {{- end }} + {{- if .Values.usePasswordFile }} + - name: postgresql-password + mountPath: /opt/bitnami/postgresql/secrets/ + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + mountPath: /dev/shm + {{- end }} + {{- if .Values.persistence.enabled }} + - name: data + mountPath: {{ .Values.persistence.mountPath }} + subPath: {{ .Values.persistence.subPath }} + {{- end }} + {{- if or (.Files.Glob "files/postgresql.conf") (.Files.Glob "files/pg_hba.conf") .Values.postgresqlConfiguration .Values.pgHbaConfiguration .Values.configurationConfigMap }} + - name: postgresql-config + mountPath: /bitnami/postgresql/conf + {{- end }} + {{- if .Values.master.extraVolumeMounts }} + {{- toYaml .Values.master.extraVolumeMounts | nindent 12 }} + {{- end }} +{{- if .Values.master.sidecars }} +{{- include "postgresql.tplValue" ( dict "value" .Values.master.sidecars "context" $ ) | nindent 8 }} +{{- end }} +{{- if .Values.metrics.enabled }} + - name: metrics + image: {{ template "postgresql.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.metrics.securityContext.enabled }} + securityContext: + runAsUser: {{ .Values.metrics.securityContext.runAsUser }} + {{- end }} + env: + {{- $database := required "In order to enable metrics you need to specify a database (.Values.postgresqlDatabase or .Values.global.postgresql.postgresqlDatabase)" (include "postgresql.database" .) }} + - name: DATA_SOURCE_URI + value: {{ printf "127.0.0.1:%d/%s?sslmode=disable" (int (include "postgresql.port" .)) $database | quote }} + {{- if .Values.usePasswordFile }} + - name: DATA_SOURCE_PASS_FILE + value: "/opt/bitnami/postgresql/secrets/postgresql-password" + {{- else }} + - name: DATA_SOURCE_PASS + valueFrom: + secretKeyRef: + name: {{ template "postgresql.secretName" . }} + key: postgresql-password + {{- end }} + - name: DATA_SOURCE_USER + value: {{ template "postgresql.username" . }} + {{- if .Values.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: / + port: http-metrics + initialDelaySeconds: {{ .Values.metrics.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.metrics.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.metrics.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.metrics.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.metrics.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: / + port: http-metrics + initialDelaySeconds: {{ .Values.metrics.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.metrics.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.metrics.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.metrics.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.metrics.readinessProbe.failureThreshold }} + {{- end }} + volumeMounts: + {{- if .Values.usePasswordFile }} + - name: postgresql-password + mountPath: /opt/bitnami/postgresql/secrets/ + {{- end }} + {{- if .Values.metrics.customMetrics }} + - name: custom-metrics + mountPath: /conf + readOnly: true + args: ["--extend.query-path", "/conf/custom-metrics.yaml"] + {{- end }} + ports: + - name: http-metrics + containerPort: 9187 + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- end }} +{{- end }} + volumes: + {{- if or (.Files.Glob "files/postgresql.conf") (.Files.Glob "files/pg_hba.conf") .Values.postgresqlConfiguration .Values.pgHbaConfiguration .Values.configurationConfigMap}} + - name: postgresql-config + configMap: + name: {{ template "postgresql.configurationCM" . }} + {{- end }} + {{- if or (.Files.Glob "files/conf.d/*.conf") .Values.postgresqlExtendedConf .Values.extendedConfConfigMap }} + - name: postgresql-extended-config + configMap: + name: {{ template "postgresql.extendedConfigurationCM" . }} + {{- end }} + {{- if .Values.usePasswordFile }} + - name: postgresql-password + secret: + secretName: {{ template "postgresql.secretName" . }} + {{- end }} + {{- if or (.Files.Glob "files/docker-entrypoint-initdb.d/*.{sh,sql,sql.gz}") .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + configMap: + name: {{ template "postgresql.initdbScriptsCM" . }} + {{- end }} + {{- if .Values.initdbScriptsSecret }} + - name: custom-init-scripts-secret + secret: + secretName: {{ template "postgresql.initdbScriptsSecret" . }} + {{- end }} + {{- if .Values.master.extraVolumes }} + {{- toYaml .Values.master.extraVolumes | nindent 8 }} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.customMetrics }} + - name: custom-metrics + configMap: + name: {{ template "postgresql.metricsCM" . }} + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + emptyDir: + medium: Memory + sizeLimit: 1Gi + {{- end }} +{{- if and .Values.persistence.enabled .Values.persistence.existingClaim }} + - name: data + persistentVolumeClaim: +{{- with .Values.persistence.existingClaim }} + claimName: {{ tpl . $ }} +{{- end }} +{{- else if not .Values.persistence.enabled }} + - name: data + emptyDir: {} +{{- else if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }} + volumeClaimTemplates: + - metadata: + name: data + {{- with .Values.persistence.annotations }} + annotations: + {{- range $key, $value := . }} + {{ $key }}: {{ $value }} + {{- end }} + {{- end }} + spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{ include "postgresql.storageClass" . }} +{{- end }} diff --git a/chart/charts/postgresql/templates/svc-headless.yaml b/chart/charts/postgresql/templates/svc-headless.yaml new file mode 100755 index 0000000000000000000000000000000000000000..5c71f468d8232628a4ae5cc3dfb250faf984fc4d --- /dev/null +++ b/chart/charts/postgresql/templates/svc-headless.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "postgresql.fullname" . }}-headless + labels: + app: {{ template "postgresql.name" . }} + chart: {{ template "postgresql.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} +spec: + type: ClusterIP + clusterIP: None + ports: + - name: tcp-postgresql + port: {{ template "postgresql.port" . }} + targetPort: tcp-postgresql + selector: + app: {{ template "postgresql.name" . }} + release: {{ .Release.Name | quote }} diff --git a/chart/charts/postgresql/templates/svc-read.yaml b/chart/charts/postgresql/templates/svc-read.yaml new file mode 100755 index 0000000000000000000000000000000000000000..d9492e2ff3ebdd91726c12fec14ea3dec261584f --- /dev/null +++ b/chart/charts/postgresql/templates/svc-read.yaml @@ -0,0 +1,31 @@ +{{- if .Values.replication.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "postgresql.fullname" . }}-read + labels: + app: {{ template "postgresql.name" . }} + chart: {{ template "postgresql.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} +{{- with .Values.service.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + type: {{ .Values.service.type }} + {{- if and .Values.service.loadBalancerIP (eq .Values.service.type "LoadBalancer") }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + ports: + - name: tcp-postgresql + port: {{ template "postgresql.port" . }} + targetPort: tcp-postgresql + {{- if .Values.service.nodePort }} + nodePort: {{ .Values.service.nodePort }} + {{- end }} + selector: + app: {{ template "postgresql.name" . }} + release: {{ .Release.Name | quote }} + role: slave +{{- end }} diff --git a/chart/charts/postgresql/templates/svc.yaml b/chart/charts/postgresql/templates/svc.yaml new file mode 100755 index 0000000000000000000000000000000000000000..0baea4ac84a198d74623c22583865b3227b1b885 --- /dev/null +++ b/chart/charts/postgresql/templates/svc.yaml @@ -0,0 +1,38 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "postgresql.fullname" . }} + labels: + app: {{ template "postgresql.name" . }} + chart: {{ template "postgresql.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} +{{- with .Values.service.annotations }} + annotations: +{{ tpl (toYaml .) $ | indent 4 }} +{{- end }} +spec: + type: {{ .Values.service.type }} + {{- if and .Values.service.loadBalancerIP (eq .Values.service.type "LoadBalancer") }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{ with .Values.service.loadBalancerSourceRanges }} +{{ toYaml . | indent 4 }} +{{- end }} + {{- end }} + {{- if and (eq .Values.service.type "ClusterIP") .Values.service.clusterIP }} + clusterIP: {{ .Values.service.clusterIP }} + {{- end }} + ports: + - name: tcp-postgresql + port: {{ template "postgresql.port" . }} + targetPort: tcp-postgresql + {{- if .Values.service.nodePort }} + nodePort: {{ .Values.service.nodePort }} + {{- end }} + selector: + app: {{ template "postgresql.name" . }} + release: {{ .Release.Name | quote }} + role: master diff --git a/chart/charts/postgresql/values-production.yaml b/chart/charts/postgresql/values-production.yaml new file mode 100755 index 0000000000000000000000000000000000000000..4abee9ec9a68e9077c742fcdc62be45e84cfa335 --- /dev/null +++ b/chart/charts/postgresql/values-production.yaml @@ -0,0 +1,520 @@ +## Global Docker image parameters +## Please, note that this will override the image parameters, including dependencies, configured to use the global value +## Current available global Docker image parameters: imageRegistry and imagePullSecrets +## +global: + postgresql: {} +# imageRegistry: myRegistryName +# imagePullSecrets: +# - myRegistryKeySecretName +# storageClass: myStorageClass + +## Bitnami PostgreSQL image version +## ref: https://hub.docker.com/r/bitnami/postgresql/tags/ +## +image: + registry: registry.dso.mil + repository: platform-one/big-bang/apps/developer-tools/sonarqube/postgresql + tag: 11.7.0-debian-10-r26 + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## + # pullSecrets: + # - myRegistryKeySecretName + + ## Set to true if you would like to see extra information on logs + ## It turns BASH and NAMI debugging in minideb + ## ref: https://github.com/bitnami/minideb-extras/#turn-on-bash-debugging + debug: false + +## String to partially override postgresql.fullname template (will maintain the release name) +## +# nameOverride: + +## String to fully override postgresql.fullname template +## +# fullnameOverride: + +## +## Init containers parameters: +## volumePermissions: Change the owner of the persist volume mountpoint to RunAsUser:fsGroup +## +volumePermissions: + enabled: false + image: + registry: registry.dso.mil + repository: platform-one/big-bang/apps/developer-tools/sonarqube/minideb:busterbitnami/minideb + tag: buster + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images + ## + pullPolicy: Always + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## + # pullSecrets: + # - myRegistryKeySecretName + ## Init container Security Context + ## Note: the chown of the data folder is done to securityContext.runAsUser + ## and not the below volumePermissions.securityContext.runAsUser + ## When runAsUser is set to special value "auto", init container will try to chwon the + ## data folder to autodetermined user&group, using commands: `id -u`:`id -G | cut -d" " -f2` + ## "auto" is especially useful for OpenShift which has scc with dynamic userids (and 0 is not allowed). + ## You may want to use this volumePermissions.securityContext.runAsUser="auto" in combination with + ## pod securityContext.enabled=false and shmVolume.chmod.enabled=false + ## + securityContext: + runAsUser: 0 + +## Use an alternate scheduler, e.g. "stork". +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +# schedulerName: + +## Pod Security Context +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ +## +securityContext: + enabled: true + fsGroup: 1001 + runAsUser: 1001 + +## Pod Service Account +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ +serviceAccount: + enabled: false + ## Name of an already existing service account. Setting this value disables the automatic service account creation. + # name: + +replication: + enabled: true + user: repl_user + password: repl_password + slaveReplicas: 2 + ## Set synchronous commit mode: on, off, remote_apply, remote_write and local + ## ref: https://www.postgresql.org/docs/9.6/runtime-config-wal.html#GUC-WAL-LEVEL + synchronousCommit: "on" + ## From the number of `slaveReplicas` defined above, set the number of those that will have synchronous replication + ## NOTE: It cannot be > slaveReplicas + numSynchronousReplicas: 1 + ## Replication Cluster application name. Useful for defining multiple replication policies + applicationName: my_application + +## PostgreSQL admin password (used when `postgresqlUsername` is not `postgres`) +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#creating-a-database-user-on-first-run (see note!) +# postgresqlPostgresPassword: + +## PostgreSQL user (has superuser privileges if username is `postgres`) +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#setting-the-root-password-on-first-run +postgresqlUsername: postgres + +## PostgreSQL password +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#setting-the-root-password-on-first-run +## +# postgresqlPassword: + +## PostgreSQL password using existing secret +## existingSecret: secret + +## Mount PostgreSQL secret as a file instead of passing environment variable +# usePasswordFile: false + +## Create a database +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#creating-a-database-on-first-run +## +# postgresqlDatabase: + +## PostgreSQL data dir +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md +## +postgresqlDataDir: /bitnami/postgresql/data + +## An array to add extra environment variables +## For example: +## extraEnv: +## - name: FOO +## value: "bar" +## +# extraEnv: +extraEnv: [] + +## Name of a ConfigMap containing extra env vars +## +# extraEnvVarsCM: + +## Specify extra initdb args +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md +## +# postgresqlInitdbArgs: + +## Specify a custom location for the PostgreSQL transaction log +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md +## +# postgresqlInitdbWalDir: + +## PostgreSQL configuration +## Specify runtime configuration parameters as a dict, using camelCase, e.g. +## {"sharedBuffers": "500MB"} +## Alternatively, you can put your postgresql.conf under the files/ directory +## ref: https://www.postgresql.org/docs/current/static/runtime-config.html +## +# postgresqlConfiguration: + +## PostgreSQL extended configuration +## As above, but _appended_ to the main configuration +## Alternatively, you can put your *.conf under the files/conf.d/ directory +## https://github.com/bitnami/bitnami-docker-postgresql#allow-settings-to-be-loaded-from-files-other-than-the-default-postgresqlconf +## +# postgresqlExtendedConf: + +## PostgreSQL client authentication configuration +## Specify content for pg_hba.conf +## Default: do not create pg_hba.conf +## Alternatively, you can put your pg_hba.conf under the files/ directory +# pgHbaConfiguration: |- +# local all all trust +# host all all localhost trust +# host mydatabase mysuser 192.168.0.0/24 md5 + +## ConfigMap with PostgreSQL configuration +## NOTE: This will override postgresqlConfiguration and pgHbaConfiguration +# configurationConfigMap: + +## ConfigMap with PostgreSQL extended configuration +# extendedConfConfigMap: + +## initdb scripts +## Specify dictionary of scripts to be run at first boot +## Alternatively, you can put your scripts under the files/docker-entrypoint-initdb.d directory +## +# initdbScripts: +# my_init_script.sh: | +# #!/bin/sh +# echo "Do something." + +## Specify the PostgreSQL username and password to execute the initdb scripts +# initdbUser: +# initdbPassword: + +## ConfigMap with scripts to be run at first boot +## NOTE: This will override initdbScripts +# initdbScriptsConfigMap: + +## Secret with scripts to be run at first boot (in case it contains sensitive information) +## NOTE: This can work along initdbScripts or initdbScriptsConfigMap +# initdbScriptsSecret: + +## Optional duration in seconds the pod needs to terminate gracefully. +## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods +## +# terminationGracePeriodSeconds: 30 + +## LDAP configuration +## +ldap: + enabled: false + url: "" + server: "" + port: "" + prefix: "" + suffix: "" + baseDN: "" + bindDN: "" + bind_password: + search_attr: "" + search_filter: "" + scheme: "" + tls: false + +## PostgreSQL service configuration +service: + ## PosgresSQL service type + type: ClusterIP + # clusterIP: None + port: 5432 + + ## Specify the nodePort value for the LoadBalancer and NodePort service types. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + # nodePort: + + ## Provide any additional annotations which may be required. + ## The value is evaluated as a template, so, for example, the value can depend on .Release or .Chart + annotations: {} + ## Set the LoadBalancer service type to internal only. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + # loadBalancerIP: + + ## Load Balancer sources + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## + # loadBalancerSourceRanges: + # - 10.10.10.0/24 + +## Start master and slave(s) pod(s) without limitations on shm memory. +## By default docker and containerd (and possibly other container runtimes) +## limit `/dev/shm` to `64M` (see e.g. the +## [docker issue](https://github.com/docker-library/postgres/issues/416) and the +## [containerd issue](https://github.com/containerd/containerd/issues/3654), +## which could be not enough if PostgreSQL uses parallel workers heavily. +## +shmVolume: + ## Set `shmVolume.enabled` to `true` to mount a new tmpfs volume to remove + ## this limitation. + ## + enabled: true + ## Set to `true` to `chmod 777 /dev/shm` on a initContainer. + ## This option is ingored if `volumePermissions.enabled` is `false` + ## + chmod: + enabled: true + +## PostgreSQL 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) +## +persistence: + enabled: true + ## A manually managed Persistent Volume and Claim + ## If defined, PVC must be created manually before volume will be bound + ## The value is evaluated as a template, so, for example, the name can depend on .Release or .Chart + ## + # existingClaim: + + ## The path the volume will be mounted at, useful when using different + ## PostgreSQL images. + ## + mountPath: /bitnami/postgresql + + ## The subdirectory of the volume to mount to, useful in dev environments + ## and one PV for multiple services. + ## + subPath: "" + + # storageClass: "-" + accessModes: + - ReadWriteOnce + size: 8Gi + annotations: {} + +## updateStrategy for PostgreSQL StatefulSet and its slaves StatefulSets +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies +updateStrategy: + type: RollingUpdate + +## +## PostgreSQL Master parameters +## +master: + ## Node, affinity, tolerations, and priorityclass settings for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#taints-and-tolerations-beta-feature + ## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption + nodeSelector: {} + affinity: {} + tolerations: [] + labels: {} + annotations: {} + podLabels: {} + podAnnotations: {} + priorityClassName: "" + ## Additional PostgreSQL Master Volume mounts + ## + extraVolumeMounts: [] + ## Additional PostgreSQL Master Volumes + ## + extraVolumes: [] + ## Add sidecars to the pod + ## + ## For example: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + sidecars: [] + +## +## PostgreSQL Slave parameters +## +slave: + ## Node, affinity, tolerations, and priorityclass settings for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#taints-and-tolerations-beta-feature + ## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption + nodeSelector: {} + affinity: {} + tolerations: [] + labels: {} + annotations: {} + podLabels: {} + podAnnotations: {} + priorityClassName: "" + extraInitContainers: | + # - name: do-something + # image: busybox + # command: ['do', 'something'] + ## Additional PostgreSQL Slave Volume mounts + ## + extraVolumeMounts: [] + ## Additional PostgreSQL Slave Volumes + ## + extraVolumes: [] + ## Add sidecars to the pod + ## + ## For example: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + sidecars: [] + +## Configure resource requests and limits +## ref: http://kubernetes.io/docs/user-guide/compute-resources/ +## +resources: + requests: + memory: 256Mi + cpu: 250m + +networkPolicy: + ## Enable creation of NetworkPolicy resources. Only Ingress traffic is filtered for now. + ## + enabled: false + + ## The Policy model to apply. When set to false, only pods with the correct + ## client label will have network access to the port PostgreSQL is listening + ## on. When true, PostgreSQL will accept connections from any source + ## (with the correct destination port). + ## + allowExternal: true + + ## if explicitNamespacesSelector is missing or set to {}, only client Pods that are in the networkPolicy's namespace + ## and that match other criteria, the ones that have the good label, can reach the DB. + ## But sometimes, we want the DB to be accessible to clients from other namespaces, in this case, we can use this + ## LabelSelector to select these namespaces, note that the networkPolicy's namespace should also be explicitly added. + ## + # explicitNamespacesSelector: + # matchLabels: + # role: frontend + # matchExpressions: + # - {key: role, operator: In, values: [frontend]} + +## Configure extra options for liveness and readiness probes +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) +livenessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + +readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + +## Configure metrics exporter +## +metrics: + enabled: true + # resources: {} + service: + type: ClusterIP + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "9187" + loadBalancerIP: + serviceMonitor: + enabled: false + additionalLabels: {} + # namespace: monitoring + # interval: 30s + # scrapeTimeout: 10s + ## Custom PrometheusRule to be defined + ## The value is evaluated as a template, so, for example, the value can depend on .Release or .Chart + ## ref: https://github.com/coreos/prometheus-operator#customresourcedefinitions + prometheusRule: + enabled: false + additionalLabels: {} + namespace: "" + rules: [] + ## These are just examples rules, please adapt them to your needs. + ## Make sure to constraint the rules to the current postgresql service. + # - alert: HugeReplicationLag + # expr: pg_replication_lag{service="{{ template "postgresql.fullname" . }}-metrics"} / 3600 > 1 + # for: 1m + # labels: + # severity: critical + # annotations: + # description: replication for {{ template "postgresql.fullname" . }} PostgreSQL is lagging by {{ "{{ $value }}" }} hour(s). + # summary: PostgreSQL replication is lagging by {{ "{{ $value }}" }} hour(s). + image: + registry: registry.dso.mil + repository: platform-one/big-bang/apps/developer-tools/sonarqube/postgres-exporter + tag: 0.8.0-debian-10-r42 + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## + # pullSecrets: + # - myRegistryKeySecretName + ## Define additional custom metrics + ## ref: https://github.com/wrouesnel/postgres_exporter#adding-new-metrics-via-a-config-file + # customMetrics: + # pg_database: + # query: "SELECT d.datname AS name, CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT') THEN pg_catalog.pg_database_size(d.datname) ELSE 0 END AS size FROM pg_catalog.pg_database d where datname not in ('template0', 'template1', 'postgres')" + # metrics: + # - name: + # usage: "LABEL" + # description: "Name of the database" + # - size_bytes: + # usage: "GAUGE" + # description: "Size of the database in bytes" + ## Pod Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + ## + securityContext: + enabled: false + runAsUser: 1001 + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) + ## Configure extra options for liveness and readiness probes + livenessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 diff --git a/chart/charts/postgresql/values.schema.json b/chart/charts/postgresql/values.schema.json new file mode 100755 index 0000000000000000000000000000000000000000..ac2de6e943250875d5b67872be3a5cb45be8ec94 --- /dev/null +++ b/chart/charts/postgresql/values.schema.json @@ -0,0 +1,103 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "postgresqlUsername": { + "type": "string", + "title": "Admin user", + "form": true + }, + "postgresqlPassword": { + "type": "string", + "title": "Password", + "form": true + }, + "persistence": { + "type": "object", + "properties": { + "size": { + "type": "string", + "title": "Persistent Volume Size", + "form": true, + "render": "slider", + "sliderMin": 1, + "sliderMax": 100, + "sliderUnit": "Gi" + } + } + }, + "resources": { + "type": "object", + "title": "Required Resources", + "description": "Configure resource requests", + "form": true, + "properties": { + "requests": { + "type": "object", + "properties": { + "memory": { + "type": "string", + "form": true, + "render": "slider", + "title": "Memory Request", + "sliderMin": 10, + "sliderMax": 2048, + "sliderUnit": "Mi" + }, + "cpu": { + "type": "string", + "form": true, + "render": "slider", + "title": "CPU Request", + "sliderMin": 10, + "sliderMax": 2000, + "sliderUnit": "m" + } + } + } + } + }, + "replication": { + "type": "object", + "form": true, + "title": "Replication Details", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enable Replication", + "form": true + }, + "slaveReplicas": { + "type": "integer", + "title": "Slave Replicas", + "form": true, + "hidden": { + "condition": false, + "value": "replication.enabled" + } + } + } + }, + "volumePermissions": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable Init Containers", + "description": "Change the owner of the persist volume mountpoint to RunAsUser:fsGroup" + } + } + }, + "metrics": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Configure metrics exporter", + "form": true + } + } + } + } +} diff --git a/chart/charts/postgresql/values.yaml b/chart/charts/postgresql/values.yaml new file mode 100755 index 0000000000000000000000000000000000000000..00c98cbc6de5820fed2f808a49743c1cccb6ae40 --- /dev/null +++ b/chart/charts/postgresql/values.yaml @@ -0,0 +1,526 @@ +## Global Docker image parameters +## Please, note that this will override the image parameters, including dependencies, configured to use the global value +## Current available global Docker image parameters: imageRegistry and imagePullSecrets +## +global: + postgresql: {} +# imageRegistry: myRegistryName +# imagePullSecrets: +# - myRegistryKeySecretName +# storageClass: myStorageClass + +## Bitnami PostgreSQL image version +## ref: https://hub.docker.com/r/bitnami/postgresql/tags/ +## +image: + registry: registry.dso.mil + repository: platform-one/big-bang/apps/developer-tools/sonarqube/postgresql + tag: 11.7.0-debian-10-r26 + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## + # pullSecrets: + # - myRegistryKeySecretName + + ## Set to true if you would like to see extra information on logs + ## It turns BASH and NAMI debugging in minideb + ## ref: https://github.com/bitnami/minideb-extras/#turn-on-bash-debugging + debug: false + +## String to partially override postgresql.fullname template (will maintain the release name) +## +# nameOverride: + +## String to fully override postgresql.fullname template +## +# fullnameOverride: + +## +## Init containers parameters: +## volumePermissions: Change the owner of the persist volume mountpoint to RunAsUser:fsGroup +## +volumePermissions: + enabled: false + image: + registry: registry.dso.mil + repository: platform-one/big-bang/apps/developer-tools/sonarqube/minideb:busterbitnami/minideb + tag: buster + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images + ## + pullPolicy: Always + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## + # pullSecrets: + # - myRegistryKeySecretName + ## Init container Security Context + ## Note: the chown of the data folder is done to securityContext.runAsUser + ## and not the below volumePermissions.securityContext.runAsUser + ## When runAsUser is set to special value "auto", init container will try to chwon the + ## data folder to autodetermined user&group, using commands: `id -u`:`id -G | cut -d" " -f2` + ## "auto" is especially useful for OpenShift which has scc with dynamic userids (and 0 is not allowed). + ## You may want to use this volumePermissions.securityContext.runAsUser="auto" in combination with + ## pod securityContext.enabled=false and shmVolume.chmod.enabled=false + ## + securityContext: + runAsUser: 0 + +## Use an alternate scheduler, e.g. "stork". +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +# schedulerName: + + +## Pod Security Context +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ +## +securityContext: + enabled: true + fsGroup: 1001 + runAsUser: 1001 + +## Pod Service Account +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ +serviceAccount: + enabled: false + ## Name of an already existing service account. Setting this value disables the automatic service account creation. + # name: + +replication: + enabled: false + user: repl_user + password: repl_password + slaveReplicas: 1 + ## Set synchronous commit mode: on, off, remote_apply, remote_write and local + ## ref: https://www.postgresql.org/docs/9.6/runtime-config-wal.html#GUC-WAL-LEVEL + synchronousCommit: "off" + ## From the number of `slaveReplicas` defined above, set the number of those that will have synchronous replication + ## NOTE: It cannot be > slaveReplicas + numSynchronousReplicas: 0 + ## Replication Cluster application name. Useful for defining multiple replication policies + applicationName: my_application + +## PostgreSQL admin password (used when `postgresqlUsername` is not `postgres`) +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#creating-a-database-user-on-first-run (see note!) +# postgresqlPostgresPassword: + +## PostgreSQL user (has superuser privileges if username is `postgres`) +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#setting-the-root-password-on-first-run +postgresqlUsername: postgres + +## PostgreSQL password +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#setting-the-root-password-on-first-run +## +# postgresqlPassword: + +## PostgreSQL password using existing secret +## existingSecret: secret + +## Mount PostgreSQL secret as a file instead of passing environment variable +# usePasswordFile: false + +## Create a database +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#creating-a-database-on-first-run +## +# postgresqlDatabase: + +## PostgreSQL data dir +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md +## +postgresqlDataDir: /bitnami/postgresql/data + +## An array to add extra environment variables +## For example: +## extraEnv: +## - name: FOO +## value: "bar" +## +# extraEnv: +extraEnv: [] + +## Name of a ConfigMap containing extra env vars +## +# extraEnvVarsCM: + +## Specify extra initdb args +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md +## +# postgresqlInitdbArgs: + +## Specify a custom location for the PostgreSQL transaction log +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md +## +# postgresqlInitdbWalDir: + +## PostgreSQL configuration +## Specify runtime configuration parameters as a dict, using camelCase, e.g. +## {"sharedBuffers": "500MB"} +## Alternatively, you can put your postgresql.conf under the files/ directory +## ref: https://www.postgresql.org/docs/current/static/runtime-config.html +## +# postgresqlConfiguration: + +## PostgreSQL extended configuration +## As above, but _appended_ to the main configuration +## Alternatively, you can put your *.conf under the files/conf.d/ directory +## https://github.com/bitnami/bitnami-docker-postgresql#allow-settings-to-be-loaded-from-files-other-than-the-default-postgresqlconf +## +# postgresqlExtendedConf: + +## PostgreSQL client authentication configuration +## Specify content for pg_hba.conf +## Default: do not create pg_hba.conf +## Alternatively, you can put your pg_hba.conf under the files/ directory +# pgHbaConfiguration: |- +# local all all trust +# host all all localhost trust +# host mydatabase mysuser 192.168.0.0/24 md5 + +## ConfigMap with PostgreSQL configuration +## NOTE: This will override postgresqlConfiguration and pgHbaConfiguration +# configurationConfigMap: + +## ConfigMap with PostgreSQL extended configuration +# extendedConfConfigMap: + +## initdb scripts +## Specify dictionary of scripts to be run at first boot +## Alternatively, you can put your scripts under the files/docker-entrypoint-initdb.d directory +## +# initdbScripts: +# my_init_script.sh: | +# #!/bin/sh +# echo "Do something." + +## ConfigMap with scripts to be run at first boot +## NOTE: This will override initdbScripts +# initdbScriptsConfigMap: + +## Secret with scripts to be run at first boot (in case it contains sensitive information) +## NOTE: This can work along initdbScripts or initdbScriptsConfigMap +# initdbScriptsSecret: + +## Specify the PostgreSQL username and password to execute the initdb scripts +# initdbUser: +# initdbPassword: + +## Optional duration in seconds the pod needs to terminate gracefully. +## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods +## +# terminationGracePeriodSeconds: 30 + +## LDAP configuration +## +ldap: + enabled: false + url: "" + server: "" + port: "" + prefix: "" + suffix: "" + baseDN: "" + bindDN: "" + bind_password: + search_attr: "" + search_filter: "" + scheme: "" + tls: false + +## PostgreSQL service configuration +service: + ## PosgresSQL service type + type: ClusterIP + # clusterIP: None + port: 5432 + + ## Specify the nodePort value for the LoadBalancer and NodePort service types. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + # nodePort: + + ## Provide any additional annotations which may be required. + ## The value is evaluated as a template, so, for example, the value can depend on .Release or .Chart + annotations: {} + ## Set the LoadBalancer service type to internal only. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + # loadBalancerIP: + + ## Load Balancer sources + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## + # loadBalancerSourceRanges: + # - 10.10.10.0/24 + +## Start master and slave(s) pod(s) without limitations on shm memory. +## By default docker and containerd (and possibly other container runtimes) +## limit `/dev/shm` to `64M` (see e.g. the +## [docker issue](https://github.com/docker-library/postgres/issues/416) and the +## [containerd issue](https://github.com/containerd/containerd/issues/3654), +## which could be not enough if PostgreSQL uses parallel workers heavily. +## +shmVolume: + ## Set `shmVolume.enabled` to `true` to mount a new tmpfs volume to remove + ## this limitation. + ## + enabled: true + ## Set to `true` to `chmod 777 /dev/shm` on a initContainer. + ## This option is ingored if `volumePermissions.enabled` is `false` + ## + chmod: + enabled: true + +## PostgreSQL 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) +## +persistence: + enabled: true + ## A manually managed Persistent Volume and Claim + ## If defined, PVC must be created manually before volume will be bound + ## The value is evaluated as a template, so, for example, the name can depend on .Release or .Chart + ## + # existingClaim: + + ## The path the volume will be mounted at, useful when using different + ## PostgreSQL images. + ## + mountPath: /bitnami/postgresql + + ## The subdirectory of the volume to mount to, useful in dev environments + ## and one PV for multiple services. + ## + subPath: "" + + # storageClass: "-" + accessModes: + - ReadWriteOnce + size: 8Gi + annotations: {} + +## updateStrategy for PostgreSQL StatefulSet and its slaves StatefulSets +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies +updateStrategy: + type: RollingUpdate + +## +## PostgreSQL Master parameters +## +master: + ## Node, affinity, tolerations, and priorityclass settings for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#taints-and-tolerations-beta-feature + ## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption + nodeSelector: {} + affinity: {} + tolerations: [] + labels: {} + annotations: {} + podLabels: {} + podAnnotations: {} + priorityClassName: "" + extraInitContainers: | + # - name: do-something + # image: busybox + # command: ['do', 'something'] + + ## Additional PostgreSQL Master Volume mounts + ## + extraVolumeMounts: [] + ## Additional PostgreSQL Master Volumes + ## + extraVolumes: [] + ## Add sidecars to the pod + ## + ## For example: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + sidecars: [] + +## +## PostgreSQL Slave parameters +## +slave: + ## Node, affinity, tolerations, and priorityclass settings for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#taints-and-tolerations-beta-feature + ## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption + nodeSelector: {} + affinity: {} + tolerations: [] + labels: {} + annotations: {} + podLabels: {} + podAnnotations: {} + priorityClassName: "" + extraInitContainers: | + # - name: do-something + # image: busybox + # command: ['do', 'something'] + ## Additional PostgreSQL Slave Volume mounts + ## + extraVolumeMounts: [] + ## Additional PostgreSQL Slave Volumes + ## + extraVolumes: [] + ## Add sidecars to the pod + ## + ## For example: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + sidecars: [] + +## Configure resource requests and limits +## ref: http://kubernetes.io/docs/user-guide/compute-resources/ +## +resources: + requests: + memory: 256Mi + cpu: 250m + +networkPolicy: + ## Enable creation of NetworkPolicy resources. Only Ingress traffic is filtered for now. + ## + enabled: false + + ## The Policy model to apply. When set to false, only pods with the correct + ## client label will have network access to the port PostgreSQL is listening + ## on. When true, PostgreSQL will accept connections from any source + ## (with the correct destination port). + ## + allowExternal: true + + ## if explicitNamespacesSelector is missing or set to {}, only client Pods that are in the networkPolicy's namespace + ## and that match other criteria, the ones that have the good label, can reach the DB. + ## But sometimes, we want the DB to be accessible to clients from other namespaces, in this case, we can use this + ## LabelSelector to select these namespaces, note that the networkPolicy's namespace should also be explicitly added. + ## + # explicitNamespacesSelector: + # matchLabels: + # role: frontend + # matchExpressions: + # - {key: role, operator: In, values: [frontend]} + +## Configure extra options for liveness and readiness probes +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) +livenessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + +readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + +## Configure metrics exporter +## +metrics: + enabled: false + # resources: {} + service: + type: ClusterIP + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "9187" + loadBalancerIP: + serviceMonitor: + enabled: false + additionalLabels: {} + # namespace: monitoring + # interval: 30s + # scrapeTimeout: 10s + ## Custom PrometheusRule to be defined + ## The value is evaluated as a template, so, for example, the value can depend on .Release or .Chart + ## ref: https://github.com/coreos/prometheus-operator#customresourcedefinitions + prometheusRule: + enabled: false + additionalLabels: {} + namespace: "" + rules: [] + ## These are just examples rules, please adapt them to your needs. + ## Make sure to constraint the rules to the current postgresql service. + # - alert: HugeReplicationLag + # expr: pg_replication_lag{service="{{ template "postgresql.fullname" . }}-metrics"} / 3600 > 1 + # for: 1m + # labels: + # severity: critical + # annotations: + # description: replication for {{ template "postgresql.fullname" . }} PostgreSQL is lagging by {{ "{{ $value }}" }} hour(s). + # summary: PostgreSQL replication is lagging by {{ "{{ $value }}" }} hour(s). + image: + registry: registry.dso.mil + repository: platform-one/big-bang/apps/developer-tools/sonarqube/postgres-exporter + tag: 0.8.0-debian-10-r42 + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## + # pullSecrets: + # - myRegistryKeySecretName + ## Define additional custom metrics + ## ref: https://github.com/wrouesnel/postgres_exporter#adding-new-metrics-via-a-config-file + # customMetrics: + # pg_database: + # query: "SELECT d.datname AS name, CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT') THEN pg_catalog.pg_database_size(d.datname) ELSE 0 END AS size FROM pg_catalog.pg_database d where datname not in ('template0', 'template1', 'postgres')" + # metrics: + # - name: + # usage: "LABEL" + # description: "Name of the database" + # - size_bytes: + # usage: "GAUGE" + # description: "Size of the database in bytes" + ## Pod Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + ## + securityContext: + enabled: false + runAsUser: 1001 + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) + ## Configure extra options for liveness and readiness probes + livenessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 diff --git a/chart/templates/NOTES.txt b/chart/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..1633b453bbd55ee0f6c33cd7718a670f1a17a537 --- /dev/null +++ b/chart/templates/NOTES.txt @@ -0,0 +1,21 @@ +{{- if not .Values.istio.enabled }} +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range .Values.ingress.hosts }} + http://{{ .name }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "sonarqube.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc -w {{ template "sonarqube.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "sonarqube.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ .Values.service.externalPort }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "sonarqube.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl port-forward $POD_NAME 8080:{{ .Values.service.externalPort }} -n {{ .Release.Namespace }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/chart/templates/_helpers.tpl b/chart/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..07d11932a54211c8fa1f0230b42ace0045096771 --- /dev/null +++ b/chart/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "sonarqube.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). +*/}} +{{- define "sonarqube.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name (include "sonarqube.name" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} + +{{/* + Create a default fully qualified mysql/postgresql name. + We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "postgresql.fullname" -}} +{{- printf "%s-%s" .Release.Name "postgresql" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* + Determine the hostname to use for PostgreSQL/mySQL. +*/}} +{{- define "postgresql.hostname" -}} +{{- if .Values.postgresql.enabled -}} +{{- printf "%s-%s" .Release.Name "postgresql" | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s" .Values.postgresql.postgresqlServer -}} +{{- end -}} +{{- end -}} + +{{/* +Set postgresql.secret +*/}} +{{- define "postgresql.secret" -}} +{{- if .Values.postgresql.existingSecret -}} +{{- .Values.postgresql.existingSecret -}} +{{- else if .Values.postgresql.enabled -}} +{{- template "postgresql.fullname" . -}} +{{- else -}} +{{- template "sonarqube.fullname" . -}} +{{- end -}} +{{- end -}} + +{{/* +Set postgresql.useInternalSecret +*/}} +{{- define "postgresql.useInternalSecret" -}} +{{- if or .Values.postgresql.enabled .Values.postgresql.existingSecret -}} +false +{{- else -}} +true +{{- end -}} +{{- end -}} diff --git a/chart/templates/change-admin-password-hook.yml b/chart/templates/change-admin-password-hook.yml new file mode 100644 index 0000000000000000000000000000000000000000..f3010b84f3d52278b4855f6c2498188173e50b4c --- /dev/null +++ b/chart/templates/change-admin-password-hook.yml @@ -0,0 +1,36 @@ +{{- if .Values.account }} +{{- if .Values.account.adminPassword }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ template "sonarqube.fullname" . }}-change-admin-password-hook + labels: + app: {{ template "sonarqube.name" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- range $key, $value := .Values.service.labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + annotations: + "helm.sh/hook": post-install + "helm.sh/hook-delete-policy": hook-succeeded +spec: + template: + metadata: + name: {{ template "sonarqube.fullname" . }}-change-admin-password-hook + labels: + app: {{ template "sonarqube.name" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + {{- range $key, $value := .Values.service.labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + spec: + restartPolicy: OnFailure + containers: + - name: {{ template "sonarqube.fullname" . }}-change-default-admin-password + image: {{ default "curlimages/curl:latest" .Values.curlContainerImage }} + command: ["sh", "-c", 'until curl -v --connect-timeout 100 {{ template "sonarqube.fullname" . }}:{{ default 9000 .Values.service.internalPort }}/api/system/status | grep -w UP; do sleep 10; done; curl -v --connect-timeout 100 -u admin:{{ default "admin" .Values.account.currentAdminPassword }} -X POST "{{ template "sonarqube.fullname" . }}:{{ default 9000 .Values.service.internalPort }}/api/users/change_password?login=admin&previousPassword={{ default "admin" .Values.account.currentAdminPassword }}&password={{ default "admin" .Values.account.adminPassword }}"'] +{{- end }} +{{- end }} diff --git a/chart/templates/config.yaml b/chart/templates/config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1ef7ada3430f0a84490e440f29d8d502d4e0823b --- /dev/null +++ b/chart/templates/config.yaml @@ -0,0 +1,25 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "sonarqube.fullname" . }}-config + labels: + app: {{ template "sonarqube.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +data: + {{- if and .Values.sonarSecretKey (not .Values.sonarProperties) (not .Values.elasticsearch.bootstrapChecks) }} + sonar.properties: sonar.secretKeyPath={{ .Values.sonarqubeFolder }}/secret/sonar-secret.txt + {{- end }} + {{- if or .Values.sonarProperties (not .Values.elasticsearch.bootstrapChecks) }} + sonar.properties: + {{ range $key, $val := .Values.sonarProperties }} + {{ $key }}={{ $val }} + {{ end }} + {{- if not .Values.elasticsearch.bootstrapChecks }} + sonar.es.bootstrap.checks.disable=true + {{- end }} + {{- end }} + {{- if and .Values.sonarSecretKey .Values.sonarProperties }} + sonar.secretKeyPath={{ .Values.sonarqubeFolder }}/secret/sonar-secret.txt + {{- end }} diff --git a/chart/templates/deployment.yaml b/chart/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4c684084124e97fb23a4307854fce349070e1689 --- /dev/null +++ b/chart/templates/deployment.yaml @@ -0,0 +1,368 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "sonarqube.fullname" . }} + labels: + app: {{ template "sonarqube.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + app.kubernetes.io/name: {{ template "sonarqube.name" . }}-{{ template "sonarqube.fullname" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/part-of: sonarqube + app.kubernetes.io/component: {{ template "sonarqube.fullname" . }} + app.kubernetes.io/version: {{ .Values.image.tag | quote }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: {{ template "sonarqube.name" . }} + release: {{ .Release.Name }} +{{- if .Values.deploymentStrategy }} + strategy: +{{ toYaml .Values.deploymentStrategy | indent 4 }} +{{- end }} + template: + metadata: + labels: + app: {{ template "sonarqube.name" . }} + release: {{ .Release.Name }} +{{- with .Values.podLabels }} +{{ toYaml . | indent 8 }} +{{- end }} + annotations: + checksum/init-sysctl: {{ include (print $.Template.BasePath "/init-sysctl.yaml") . | sha256sum }} + checksum/plugins: {{ include (print $.Template.BasePath "/install-plugins.yaml") . | sha256sum }} + checksum/config: {{ include (print $.Template.BasePath "/config.yaml") . | sha256sum }} + checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} +{{- if .Values.annotations}} + {{- range $key, $value := .Values.annotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} +{{- end }} + spec: + {{- if .Values.schedulerName }} + schedulerName: {{ .Values.schedulerName }} + {{- end }} + {{- if .Values.serviceAccount.create }} + {{- if .Values.serviceAccount.name }} + serviceAccountName: {{ .Values.serviceAccount.name }} + {{- else }} + serviceAccountName: {{ include "sonarqube.fullname" . }} + {{- end }} + {{- end }} + securityContext: +{{ toYaml .Values.securityContext | indent 8 }} + {{- if .Values.image.pullSecret }} + imagePullSecrets: + - name: {{ .Values.image.pullSecret }} + {{- end }} + initContainers: + {{- if .Values.caCerts }} + - name: ca-certs + image: {{ default "adoptopenjdk/openjdk11:alpine" .Values.caCerts.image }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: ["sh"] + args: ["-c", "cp -f \"${JAVA_HOME}/lib/security/cacerts\" /tmp/certs/cacerts; if [ \"$(ls /tmp/secrets/ca-certs)\" ]; then for f in /tmp/secrets/ca-certs/*; do keytool -importcert -file \"${f}\" -alias \"$(basename \"${f}\")\" -keystore /tmp/certs/cacerts -storepass changeit -trustcacerts -noprompt; done; fi;"] + {{- if $securityContext := .Values.initContainers.securityContext }} + securityContext: +{{ toYaml $securityContext | indent 12 }} + {{- end }} + resources: +{{ toYaml .Values.initContainers.resources | indent 12 }} + volumeMounts: + - mountPath: /tmp/certs + name: sonarqube + subPath: certs + - mountPath: /tmp/secrets/ca-certs + name: ca-certs + {{- with .Values.env }} + env: + {{- . | toYaml | trim | nindent 12 }} + {{- end }} + {{- end }} + {{- if or .Values.initSysctl.enabled .Values.elasticsearch.configureNode }} + - name: init-sysctl + image: {{ default "busybox:1.32" .Values.initSysctl.image }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if $securityContext := (default .Values.initContainers.securityContext .Values.initSysctl.securityContext) }} + securityContext: +{{ toYaml $securityContext | indent 12 }} + {{- end }} + resources: +{{ toYaml (default .Values.initContainers.resources .Values.initSysctl.resources) | indent 12 }} + command: ["sh", + "-e", + "/tmp/scripts/init_sysctl.sh"] + volumeMounts: + - name: init-sysctl + mountPath: /tmp/scripts/ + {{- with .Values.env }} + env: + {{- . | toYaml | trim | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.plugins.install }} + - name: install-plugins + image: {{ default "rjkernick/alpine-wget:latest" .Values.plugins.image }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: ["sh", + "-e", + "/tmp/scripts/install_plugins.sh"] + volumeMounts: + - mountPath: {{ .Values.sonarqubeFolder }}/extensions/downloads + name: sonarqube + subPath: extensions/downloads + - mountPath: {{ .Values.sonarqubeFolder }}/lib/common + name: sonarqube + subPath: lib/common + - name: install-plugins + mountPath: /tmp/scripts/ + {{- if .Values.plugins.netrcCreds }} + - name: plugins-netrc-file + mountPath: /root + {{- end }} + {{- if $securityContext := .Values.initContainers.securityContext }} + securityContext: +{{ toYaml $securityContext | indent 12 }} + {{- end }} + resources: +{{ toYaml (default .Values.initContainers.resources .Values.plugins.resource) | indent 12 }} + {{- with .Values.env }} + env: + {{- . | toYaml | trim | nindent 12 }} + {{- end }} + {{- end }} + {{- if and .Values.sonarProperties .Values.sonarSecretProperties }} + - name: concat-properties + image: {{ default "busybox:1.32" .Values.initContainers.image }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: ["sh", + "-c", + "awk 1 /tmp/props/sonar.properties /tmp/props/secret.properties > /tmp/result/sonar.properties"] + volumeMounts: + - mountPath: /tmp/props/sonar.properties + name: config + subPath: sonar.properties + - mountPath: /tmp/props/secret.properties + name: secret-config + subPath: secret.properties + - mountPath: /tmp/result + name: concat-dir + {{- if $securityContext := .Values.initContainers.securityContext }} + securityContext: +{{ toYaml $securityContext | indent 12 }} + {{- end }} + resources: +{{ toYaml .Values.initContainers.resources | indent 12 }} + {{- with .Values.env }} + env: + {{- . | toYaml | trim | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.postgresql.enabled }} + - name: "wait-for-db" + image: {{ default "busybox:1.32" .Values.initContainers.image }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + resources: +{{ toYaml .Values.initContainers.resources | indent 12 }} + command: ["/bin/sh", "-c", "for i in $(seq 1 200); do nc -z -w3 {{ .Release.Name}}-postgresql 5432 && exit 0 || sleep 2; done; exit 1"] + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: +{{ toYaml .Values.nodeSelector | indent 8 }} + {{- end }} + {{- if .Values.hostAliases }} + hostAliases: +{{ toYaml .Values.hostAliases | indent 8 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: +{{ toYaml .Values.tolerations | indent 8 }} + {{- end }} + {{- if .Values.affinity }} + affinity: +{{ toYaml .Values.affinity | indent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.internalPort }} + protocol: TCP + env: + {{- with .Values.env }} + {{- . | toYaml | trim | nindent 12 }} + {{- end }} + - name: SONAR_WEB_JAVAOPTS + {{- if .Values.caCerts }} + value: {{ printf "-Djavax.net.ssl.trustStore=%s/certs/cacerts %s" .Values.sonarqubeFolder .Values.jvmOpts | trim | quote }} + {{- else }} + value: "{{ .Values.jvmOpts }}" + {{- end }} + {{- if .Values.caCerts }} + - name: SONAR_CE_JAVAOPTS + value: {{ printf "-Djavax.net.ssl.trustStore=%s/certs/cacerts" .Values.sonarqubeFolder | trim | quote }} + {{- end }} + - name: SONAR_JDBC_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "postgresql.secret" . }} + key: postgresql-password + envFrom: + - configMapRef: + name: {{ template "sonarqube.fullname" . }}-postgres-config +{{- range .Values.extraConfig.secrets }} + - secretRef: + name: {{ . }} +{{- end }} +{{- range .Values.extraConfig.configmaps }} + - configMapRef: + name: {{ . }} +{{- end }} + livenessProbe: + httpGet: + path: {{ .Values.livenessProbe.sonarWebContext }}api/system/status + port: http + initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.livenessProbe.periodSeconds }} + readinessProbe: + httpGet: + path: {{ .Values.readinessProbe.sonarWebContext }}api/system/status + port: http + initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + {{- if .Values.containerSecurityContext }} + securityContext: +{{- toYaml .Values.containerSecurityContext | nindent 12 }} + {{- end }} + volumeMounts: +{{- if .Values.persistence.mounts }} +{{ toYaml .Values.persistence.mounts | indent 12 }} +{{- end }} + {{- if and .Values.sonarProperties .Values.sonarSecretProperties }} + - mountPath: {{ .Values.sonarqubeFolder }}/conf/ + name: concat-dir + {{- else if or .Values.sonarProperties (not .Values.elasticsearch.bootstrapChecks) }} + - mountPath: {{ .Values.sonarqubeFolder }}/conf/ + name: config + {{- end }} + {{- if .Values.sonarSecretKey }} + - mountPath: {{ .Values.sonarqubeFolder }}/secret/ + name: secret + {{- end }} + {{- if .Values.caCerts }} + - mountPath: {{ .Values.sonarqubeFolder }}/certs + name: sonarqube + subPath: certs + {{- end }} + - mountPath: {{ .Values.sonarqubeFolder }}/data + name: sonarqube + subPath: data + {{- if .Values.plugins.install }} + - mountPath: {{ .Values.sonarqubeFolder }}/extensions/downloads + name: sonarqube + subPath: extensions/downloads + {{- end }} + {{- if .Values.plugins.lib }} + {{- range $index, $val := .Values.plugins.lib }} + - mountPath: {{ $.Values.sonarqubeFolder }}/lib/common/{{ $val }} + name: sonarqube + subPath: lib/common/{{ $val }} + {{- end }} + {{- end }} + - mountPath: {{ .Values.sonarqubeFolder }}/temp + name: sonarqube + subPath: temp + - mountPath: {{ .Values.sonarqubeFolder }}/logs + name: sonarqube + subPath: logs + - mountPath: /tmp + name: tmp-dir + resources: +{{ toYaml .Values.resources | indent 12 }} + {{- if .Values.nodeSelector }} + nodeSelector: +{{ toYaml .Values.nodeSelector | indent 8 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: +{{ toYaml .Values.tolerations | indent 8 }} + {{- end }} + {{- if .Values.affinity }} + affinity: +{{ toYaml .Values.affinity | indent 8 }} + {{- end }} + volumes: +{{- if .Values.persistence.volumes }} +{{ tpl (toYaml .Values.persistence.volumes | indent 6) . }} +{{- end }} + {{- if or .Values.sonarProperties (not .Values.elasticsearch.bootstrapChecks) }} + - name: config + configMap: + name: {{ template "sonarqube.fullname" . }}-config + items: + - key: sonar.properties + path: sonar.properties + {{- end }} + {{- if .Values.sonarSecretProperties }} + - name: secret-config + secret: + secretName: {{ .Values.sonarSecretProperties }} + items: + - key: secret.properties + path: secret.properties + {{- end }} + {{- if .Values.sonarSecretKey }} + - name: secret + secret: + secretName: {{ .Values.sonarSecretKey }} + items: + - key: sonar-secret.txt + path: sonar-secret.txt + {{- end }} + {{- if .Values.caCerts }} + - name: ca-certs + secret: + secretName: {{ .Values.caCerts.secret }} + {{- end }} + {{- if .Values.plugins.netrcCreds }} + - name: plugins-netrc-file + secret: + secretName: {{ .Values.plugins.netrcCreds }} + items: + - key: netrc + path: .netrc + {{- end }} + - name: init-sysctl + configMap: + name: {{ template "sonarqube.fullname" . }}-init-sysctl + items: + - key: init_sysctl.sh + path: init_sysctl.sh + - name: install-plugins + configMap: + name: {{ template "sonarqube.fullname" . }}-install-plugins + items: + - key: install_plugins.sh + path: install_plugins.sh + - name: sonarqube + {{- if .Values.persistence.enabled }} + persistentVolumeClaim: + claimName: {{ if .Values.persistence.existingClaim }}{{ .Values.persistence.existingClaim }}{{- else }}{{ template "sonarqube.fullname" . }}{{- end }} + {{- else }} + emptyDir: {{- toYaml .Values.emptyDir | nindent 10 }} + {{- end }} + - name : tmp-dir + emptyDir: {{- toYaml .Values.emptyDir | nindent 10 }} + {{- if .Values.sonarSecretProperties }} + - name : concat-dir + emptyDir: {{- toYaml .Values.emptyDir | nindent 10 -}} + {{- end }} diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..11d8c2b944d15e577cfea0d3023efc1d3899326e --- /dev/null +++ b/chart/templates/ingress.yaml @@ -0,0 +1,41 @@ +{{- if .Values.ingress.enabled -}} +{{- $serviceName := include "sonarqube.fullname" . -}} +{{- $servicePort := .Values.service.externalPort -}} +{{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" }} +apiVersion: networking.k8s.io/v1beta1 +{{ else }} +apiVersion: extensions/v1beta1 +{{ end -}} +kind: Ingress +metadata: + name: {{ template "sonarqube.fullname" . }} + labels: + app: {{ template "sonarqube.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- if .Values.ingress.labels }} +{{ .Values.ingress.labels | toYaml | trimSuffix "\n"| indent 4 -}} +{{- end}} +{{- if .Values.ingress.annotations}} + annotations: + {{- range $key, $value := .Values.ingress.annotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} +{{- end }} +spec: + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .name }} + http: + paths: + - path: {{ .path}} + backend: + serviceName: {{ default $serviceName .serviceName }} + servicePort: {{ default $servicePort .servicePort }} + {{- end -}} + {{- if .Values.ingress.tls }} + tls: +{{ toYaml .Values.ingress.tls | indent 4 }} + {{- end -}} +{{- end -}} diff --git a/chart/templates/init-sysctl.yaml b/chart/templates/init-sysctl.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b400ab42fdf7410894873d183e353f8884168e65 --- /dev/null +++ b/chart/templates/init-sysctl.yaml @@ -0,0 +1,37 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "sonarqube.fullname" . }}-init-sysctl + labels: + app: {{ template "sonarqube.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +data: + init_sysctl.sh: |- + {{- if .Values.initSysctl.vmMaxMapCount }} + if [[ "$(sysctl -n vm.max_map_count)" -lt {{ .Values.initSysctl.vmMaxMapCount }} ]]; then + sysctl -w vm.max_map_count={{ .Values.initSysctl.vmMaxMapCount }} + fi + {{- end }} + {{- if .Values.initSysctl.fsFileMax }} + if [[ "$(sysctl -n fs.file-max)" -lt {{ .Values.initSysctl.fsFileMax }} ]]; then + sysctl -w fs.file-max={{ .Values.initSysctl.fsFileMax }} + fi + {{- end }} + {{- if .Values.initSysctl.nofile }} + if [[ "$(ulimit -n)" != "unlimited" ]]; then + if [[ "$(ulimit -n)" -lt {{ .Values.initSysctl.nofile }} ]]; then + echo "ulimit -n {{ .Values.initSysctl.nofile }}" + ulimit -n {{ .Values.initSysctl.nofile }} + fi + fi + {{- end }} + {{- if .Values.initSysctl.nproc }} + if [[ "$(ulimit -u)" != "unlimited" ]]; then + if [[ "$(ulimit -u)" -lt {{ .Values.initSysctl.nproc }} ]]; then + echo "ulimit -u {{ .Values.initSysctl.nproc }}" + ulimit -u {{ .Values.initSysctl.nproc }} + fi + fi + {{- end }} diff --git a/chart/templates/install-plugins.yaml b/chart/templates/install-plugins.yaml new file mode 100644 index 0000000000000000000000000000000000000000..618653ae317f9a6740a8731f5356e20368e41551 --- /dev/null +++ b/chart/templates/install-plugins.yaml @@ -0,0 +1,32 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "sonarqube.fullname" . }}-install-plugins + labels: + app: {{ template "sonarqube.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +data: + install_plugins.sh: |- + {{- if .Values.plugins.httpProxy }} + export http_proxy={{ .Values.plugins.httpProxy }} + {{- end }} + {{- if .Values.plugins.httpsProxy }} + export https_proxy={{ .Values.plugins.httpsProxy }} + {{- end }} + {{- if .Values.plugins.noProxy }} + export no_proxy={{ .Values.plugins.noProxy }} + {{- end }} + {{- if .Values.plugins.install }} + [ -e {{ .Values.sonarqubeFolder }}/extensions/downloads/* ] && rm {{ .Values.sonarqubeFolder }}/extensions/downloads/* + {{ range $index, $val := .Values.plugins.install }} + echo {{ $val | quote }} >> {{ $.Values.sonarqubeFolder }}/extensions/downloads/list{{ end }} + cat {{ .Values.sonarqubeFolder }}/extensions/downloads/list | xargs -n 1 -P 8 wget --directory-prefix {{ .Values.sonarqubeFolder }}/extensions/downloads --no-verbose + rm {{ .Values.sonarqubeFolder }}/extensions/downloads/list + {{- end }} + {{- if .Values.plugins.lib }} + {{- range $index, $val := .Values.plugins.lib }} + cp -f {{ $.Values.sonarqubeFolder }}/extensions/downloads/{{ $val }} {{ $.Values.sonarqubeFolder }}/lib/common/{{ $val }} + {{- end }} + {{- end }} diff --git a/chart/templates/postgres-config.yaml b/chart/templates/postgres-config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ee26ba1b2ffae5d8657590a551df7134e38a84a1 --- /dev/null +++ b/chart/templates/postgres-config.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "sonarqube.fullname" . }}-postgres-config + labels: + app: {{ template "sonarqube.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +data: +{{- if .Values.postgresql.postgresqlUsername }} + SONAR_JDBC_USERNAME: {{ .Values.postgresql.postgresqlUsername | quote }} +{{- end }} +{{- if .Values.jdbcUrlOverride }} + SONAR_JDBC_URL: "{{- .Values.jdbcUrlOverride -}}" +{{- else if and .Values.postgresql.service.port .Values.postgresql.postgresqlDatabase }} + SONAR_JDBC_URL: "jdbc:{{- .Values.jdbcDatabaseType -}}://{{ template "postgresql.hostname" . }}:{{- .Values.postgresql.service.port -}}/{{- .Values.postgresql.postgresqlDatabase -}}" +{{- end }} diff --git a/chart/templates/pvc.yaml b/chart/templates/pvc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..03b837e8d31908173c51823bb2f2c5c1d26c6441 --- /dev/null +++ b/chart/templates/pvc.yaml @@ -0,0 +1,30 @@ +{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ template "sonarqube.fullname" . }} + labels: + app: {{ template "sonarqube.name" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" +{{ if .Values.persistence.annotations}} + annotations: + {{- range $key, $value := .Values.persistence.annotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} +{{- end }} +spec: + accessModes: + - {{ .Values.persistence.accessMode | quote }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} +{{- if .Values.persistence.storageClass }} +{{- if (eq "-" .Values.persistence.storageClass) }} + storageClassName: "" +{{- else }} + storageClassName: "{{ .Values.persistence.storageClass }}" +{{- end }} +{{- end }} +{{- end }} diff --git a/chart/templates/secret.yaml b/chart/templates/secret.yaml new file mode 100644 index 0000000000000000000000000000000000000000..220be8e4a0507b80851033c6ae4853f7e3cda937 --- /dev/null +++ b/chart/templates/secret.yaml @@ -0,0 +1,14 @@ +{{- if eq (include "postgresql.useInternalSecret" .) "true" -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "sonarqube.fullname" . }} + labels: + app: {{ template "sonarqube.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +type: Opaque +data: + postgresql-password: {{ .Values.postgresql.postgresqlPassword | b64enc | quote }} +{{- end -}} diff --git a/chart/templates/service.yaml b/chart/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c61fe09b87ce919a66a2fc7654ac0c3762d872a6 --- /dev/null +++ b/chart/templates/service.yaml @@ -0,0 +1,39 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "sonarqube.fullname" . }} + labels: + app: {{ template "sonarqube.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + {{- range $key, $value := .Values.service.labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} +{{ if .Values.service.annotations}} + annotations: + {{- range $key, $value := .Values.service.annotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} +{{- end }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.externalPort }} + targetPort: http + protocol: TCP + name: http + selector: + app: {{ template "sonarqube.name" . }} + release: {{ .Release.Name }} + {{- if eq .Values.service.type "LoadBalancer"}} + {{- if .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- range .Values.service.loadBalancerSourceRanges }} + - {{ . }} + {{- end }} + {{- end -}} + {{- if .Values.service.loadBalancerIP}} + loadBalancerIP: {{.Values.service.loadBalancerIP}} + {{- end }} + {{- end }} diff --git a/chart/templates/serviceaccount.yaml b/chart/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a4103db18497c1b43f538d4e120d099fad7ce030 --- /dev/null +++ b/chart/templates/serviceaccount.yaml @@ -0,0 +1,15 @@ +{{- if .Values.serviceAccount.create -}} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: +{{- if .Values.serviceAccount.name }} + name: {{ .Values.serviceAccount.name }} +{{- else }} + name: {{ include "sonarqube.fullname" . }} +{{- end }} +{{- if .Values.serviceAccount.annotations }} + annotations: +{{ toYaml .Values.serviceAccount.annotations | indent 4 }} +{{- end }} +{{- end -}} diff --git a/chart/templates/sonarqube-scc.yaml b/chart/templates/sonarqube-scc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..151dff343c65d00da915e4e47b6b9f29cac30c62 --- /dev/null +++ b/chart/templates/sonarqube-scc.yaml @@ -0,0 +1,63 @@ +{{- if and (.Values.OpenShift.enabled) (.Values.OpenShift.createSCC) }} + +# This SCC allows any user ID but restricts capabilties and host access +apiVersion: security.openshift.io/v1 +kind: SecurityContextConstraints +metadata: + annotations: + kubernetes.io/description: "allows pod to run as root, privileged and run sysctl" + "helm.sh/hook": pre-install + name: {{ .Release.Name }}-privileged-scc +allowHostDirVolumePlugin: false +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegedContainer: true +allowPrivilegeEscalation: true +allowedCapabilities: [] +allowedFlexVolumes: [] +allowedUnsafeSysctls: [] +defaultAddCapabilities: [] +defaultAllowPrivilegeEscalation: true +fsGroup: + type: RunAsAny +readOnlyRootFilesystem: false +requiredDropCapabilities: +- KILL +- MKNOD +- SETUID +- SETGID +runAsUser: + type: RunAsAny +# This can be customized for your host machine +seLinuxContext: + type: MustRunAs +# seLinuxOptions: +# level: +# user: +# role: +# type: +supplementalGroups: + type: RunAsAny +# This can be customized for your host machine +volumes: +- configMap +- downwardAPI +- emptyDir +- persistentVolumeClaim +- projected +- secret +# If you want a priority on your SCC -- set for a value more than 0 +priority: 11 +users: +{{- if .Values.serviceAccount.name }} +- system:serviceaccount:{{ .Release.Namespace }}:{{ .Release.Name }}-{{ .Values.serviceAccount.name }} +{{- else }} +- system:serviceaccount:{{ .Release.Namespace }}:{{ .Release.Name }}-sonarqube +{{- end }} +{{- if .Values.postgresql.securityContext.enabled }} +- system:serviceaccount:{{ .Release.Namespace }}:{{ .Release.Name }}-postgresql +{{- end }} + +{{- end }} diff --git a/chart/templates/tests/sonarqube-test.yaml b/chart/templates/tests/sonarqube-test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9ecef43edb490f256c0b7a2e8d52922867d296aa --- /dev/null +++ b/chart/templates/tests/sonarqube-test.yaml @@ -0,0 +1,47 @@ +{{- if .Values.tests.enabled -}} +apiVersion: v1 +kind: Pod +metadata: + name: "{{ .Release.Name }}-ui-test" + annotations: + "helm.sh/hook": test-success + labels: + app: {{ template "sonarqube.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + initContainers: + - name: "bats" + image: "bats/bats:1.2.1" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: ["bash", "-c"] + args: + - |- + set -ex + cp -R /opt/bats /tools/bats/ + volumeMounts: + - mountPath: /tools + name: tools + containers: + - name: {{ .Release.Name }}-ui-test + image: {{ default "bitnami/minideb-extras" .Values.tests.image }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: [ + "/tools/bats/bin/bats", + "--tap", + "/tests/run.sh"] + volumeMounts: + - mountPath: /tests + name: tests + readOnly: true + - mountPath: /tools + name: tools + volumes: + - name: tests + configMap: + name: {{ template "sonarqube.fullname" . }}-tests + - name: tools + emptyDir: {{ toYaml .Values.emptyDir | nindent 6 }} + restartPolicy: Never +{{- end -}} diff --git a/chart/templates/tests/test-config.yaml b/chart/templates/tests/test-config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..012be0331a40a24690f648f9d2b7ee6cb5db5620 --- /dev/null +++ b/chart/templates/tests/test-config.yaml @@ -0,0 +1,16 @@ +{{- if .Values.tests.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "sonarqube.fullname" . }}-tests + labels: + app: {{ template "sonarqube.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +data: + run.sh: |- + @test "Testing Sonarqube UI is accessible" { + curl --connect-timeout 5 --retry 12 --retry-delay 1 --retry-max-time 60 {{ template "sonarqube.fullname" . }}:{{ .Values.service.internalPort }}/api/system/status + } +{{- end -}} diff --git a/chart/templates/virtualservice.yaml b/chart/templates/virtualservice.yaml new file mode 100644 index 0000000000000000000000000000000000000000..341c0c5fb5eb33f1501f52f1003fa6359878bfed --- /dev/null +++ b/chart/templates/virtualservice.yaml @@ -0,0 +1,23 @@ +{{- if .Values.istio.enabled -}} +{{- $serviceName := include "sonarqube.fullname" . -}} +apiVersion: networking.istio.io/v1beta1 +kind: VirtualService +metadata: + name: {{ template "sonarqube.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/part-of: sonarqube +spec: + gateways: + - istio-system/main + hosts: + - "sonarqube.{{ .Values.hostname }}" + http: + - route: + - destination: + port: + number: {{ .Values.service.externalPort }} + host: {{ $serviceName }} +{{- end }} diff --git a/chart/values.yaml b/chart/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..527bbcc5dd85c8d6e2ee5b2342a4c8f04c611e69 --- /dev/null +++ b/chart/values.yaml @@ -0,0 +1,355 @@ +# Default values for sonarqube. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +replicaCount: 1 + + # This will use the default deployment strategy unless it is overriden +deploymentStrategy: {} +# Uncomment this to scheduler pods on priority +# priorityClassName: "high-priority" + +## Use an alternate scheduler, e.g. "stork". +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +# schedulerName: + +## Is this deployment for OpenShift? If so, we help with SCCs +OpenShift: + enabled: false + createSCC: true + +image: + repository: registry1.dso.mil/ironbank/sonarsource/sonarqube/sonarqube8-community + tag: 8.6-community + pullPolicy: IfNotPresent + # If using a private repository, the name of the imagePullSecret to use + pullSecret: [] + +# Set security context for sonarqube pod +securityContext: + fsGroup: 1000 + +# Set security context for sonarqube container +containerSecurityContext: + # Sonarqube dockerfile creates sonarqube user as UID and GID 1000 + runAsUser: 1000 + +# Settings to configure elasticsearch host requirements +elasticsearch: + # DEPRECATED: Use initSysctl.enabled instead + configureNode: true + bootstrapChecks: true + +service: + type: ClusterIP + externalPort: 9000 + internalPort: 9000 + labels: + annotations: {} + # May be used in example for internal load balancing in GCP: + # cloud.google.com/load-balancer-type: Internal + # loadBalancerSourceRanges: + # - 0.0.0.0/0 + # loadBalancerIP: 1.2.3.4 +ingress: + enabled: false + # Used to create an Ingress record. + hosts: + - name: sonar.example.com + # Different clouds or configurations might need /* as the default path + path: / + # For additional control over serviceName and servicePort + # serviceName: someService + # servicePort: somePort + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + # This property allows for reports up to a certain size to be uploaded to SonarQube + # nginx.ingress.kubernetes.io/proxy-body-size: "8m" + +# Additional labels for Ingress manifest file + # labels: + # traffic-type: external + # traffic-type: internal + tls: [] + # Secrets must be manually created in the namespace. + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +# Affinity for pod assignment +# Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +affinity: {} + +# Tolerations for pod assignment +# Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +tolerations: [] + +# Node labels for pod assignment +# Ref: https://kubernetes.io/docs/user-guide/node-selection/ +nodeSelector: {} + +# hostAliases allows the modification of the hosts file inside a container +hostAliases: [] +# - ip: "192.168.1.10" +# hostnames: +# - "example.com" +# - "www.example.com" + +readinessProbe: + initialDelaySeconds: 60 + periodSeconds: 30 + failureThreshold: 6 + # If an ingress *path* other than the root (/) is defined, it should be reflected here + # A trailing "/" must be included + sonarWebContext: / + # sonarWebContext: /sonarqube/ +livenessProbe: + initialDelaySeconds: 60 + periodSeconds: 30 + # If an ingress *path* other than the root (/) is defined, it should be reflected here + # A trailing "/" must be included + sonarWebContext: / + # sonarWebContext: /sonarqube/ + # If an ingress *path* is defined, it should be reflected here + # sonar.web.context: /sonarqube + +initContainers: + # image: busybox:1.32 + # We allow the init containers to have a separate security context declaration because + # the initContainer may not require the same as SonarQube. + # securityContext: {} + # We allow the init containers to have a separate resources declaration because + # the initContainer does not take as much resources. + resources: {} + +## Provide a secret containing one or more certificate files in the keys that will be added to cacerts +## The cacerts file will be set via SONARQUBE_WEB_JVM_OPTS and SONAR_CE_JAVAOPTS +## +# caCerts: + # image: adoptopenjdk/openjdk11:alpine + # secret: my-secret + +initSysctl: + enabled: true + vmMaxMapCount: 524288 + fsFileMax: 131072 + nofile: 131072 + nproc: 8192 + # image: busybox:1.32 + securityContext: + privileged: true + # resources: {} + +# List of plugins to install. +# For example: +# plugins: +# install: +# - "https://github.com/AmadeusITGroup/sonar-stash/releases/download/1.3.0/sonar-stash-plugin-1.3.0.jar" +# - "https://github.com/SonarSource/sonar-ldap/releases/download/2.2-RC3/sonar-ldap-plugin-2.2.0.601.jar" +plugins: + install: [] + lib: [] + + # For use behind a corporate proxy when downloading plugins + # httpProxy: "" + # httpsProxy: "" + # noProxy: "" + + # image: rjkernick/alpine-wget:latest + # resources: {} + + # .netrc secret file with a key "netrc" to use basic auth while downloading plugins + # netrcCreds: "" + +## Values to add to SONARQUBE_WEB_JVM_OPTS +## +# jvmOpts: "-Djava.net.preferIPv4Stack=true" +jvmOpts: "" + +## Environment variables to attach to the pods +## +# env: +# - name: VARIABLE +# value: my-value + +# Set annotations for pods +annotations: {} + +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 +persistence: + enabled: false + ## Set annotations on pvc + annotations: {} + + ## Specify an existing volume claim instead of creating a new one. + ## When using this option all following options like storageClass, accessMode and size are ignored. + # existingClaim: + + ## 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: + accessMode: ReadWriteOnce + size: 10Gi + + ## Specify extra volumes. Refer to ".spec.volumes" specification : https://kubernetes.io/fr/docs/concepts/storage/volumes/ + volumes: [] + ## Specify extra mounts. Refer to ".spec.containers.volumeMounts" specification : https://kubernetes.io/fr/docs/concepts/storage/volumes/ + mounts: [] + +# In case you want to specify different resources for emptyDir than {} +emptyDir: {} + # Example of resouces that might be used: + # medium: Memory + # sizeLimit: 16Mi + +# A custom sonar.properties file can be provided via dictionary. +# For example: +sonarProperties: + sonar.forceAuthentication: true +# SAML SSO config +# sonar.core.serverBaseURL: +# sonar.auth.saml.enabled: false +# sonar.auth.saml.applicationId: +# sonar.auth.saml.providerName: +# sonar.auth.saml.providerId: +# sonar.auth.saml.loginUrl: +# sonar.auth.saml.certificate.secured: +# sonar.auth.saml.user.login: +# sonar.auth.saml.user.name: +# sonar.auth.saml.user.email: +# sonar.auth.saml.group.name: + +# Additional sonar properties to load from a secret with a key "secret.properties" (must be a string) +# sonarSecretProperties: + +# Kubernetes secret that contains the encryption key for the sonarqube instance. +# The secret must contain the key 'sonar-secret.txt'. +# The 'sonar.secretKeyPath' property will be set automatically. +# sonarSecretKey: "settings-encryption-secret" + +## JDBC Database Type; by default postgresql. To use a different Database type, adjust +jdbcDatabaseType: postgresql + +## Override JDBC URL +# jdbcUrlOverride: "jdbc:postgresql://myPostgress/myDatabase;socketTimeout=1500" + +## Configuration values for postgresql dependency +## ref: https://github.com/kubernetes/charts/blob/master/stable/postgresql/README.md +postgresql: + # Enable to deploy the PostgreSQL chart + enabled: true + # To use an external PostgreSQL instance, set enabled to false and uncomment + # the line below: + # postgresqlServer: "" + # To use an external secret for the password for an external PostgreSQL + # instance, set enabled to false and provide the name of the secret on the + # line below: + # existingSecret: "" + postgresqlUsername: "sonarUser" + postgresqlPassword: "sonarPass" + postgresqlDatabase: "sonarDB" + # Specify the TCP port that PostgreSQL should use + service: + port: 5432 + resources: + limits: + cpu: 2 + memory: 2Gi + requests: + cpu: 100m + memory: 200Mi + persistence: + enabled: true + accessMode: ReadWriteOnce + size: 20Gi + storageClass: + securityContext: + # For standard Kubernetes deployment, set enabled=true + # If using OpenShift, enabled=false for restricted SCC and enabled=true for anyuid/nonroot SCC + enabled: true + # fsGroup and runAsUser specifications below are not applied if enabled=false. enabled=false is the required setting for OpenShift "restricted SCC" to work successfully. + # postgresql dockerfile sets user as 1001 + fsGroup: 1001 + runAsUser: 1001 + volumePermissions: + # For standard Kubernetes deployment, set enabled=false + # For OpenShift, set enabled=true and ensure to set volumepermissions.securitycontext.runAsUser below. + enabled: false + # if using restricted SCC set runAsUser: "auto" and if running under anyuid/nonroot SCC - runAsUser needs to match runAsUser above + securityContext: + runAsUser: 0 + shmVolume: + chmod: + enabled: false + serviceAccount: + ## If enabled = true, and name is not set, postgreSQL will create a serviceAccount + enabled: false +# name: + +# Additional labels to add to the pods: +# podLabels: +# key: value +podLabels: {} +# For compatibility with 8.0 replace by "/opt/sq" +# For compatibility with 8.2, leave the default. They changed it back to /opt/sonarqube +sonarqubeFolder: /opt/sonarqube + +tests: + enabled: true + # image: bitnami/minideb-extras + +serviceAccount: + create: false + # name: + ## Annotations for the Service Account + annotations: {} + +# extraConfig is used to load Environment Variables from Secrets and ConfigMaps +# which may have been written by other tools, such as external orchestrators. +# +# These Secrets/ConfigMaps are expected to contain Key/Value pairs, such as: +# +# apiVersion: v1 +# kind: ConfigMap +# metadata: +# name: external-sonarqube-opts +# data: +# SONARQUBE_JDBC_USERNAME: foo +# SONARQUBE_JDBC_URL: jdbc:postgresql://db.example.com:5432/sonar +# +# These vars can then be injected into the environment by uncommenting the following: +# +# extraConfig: +# configmaps: +# - external-sonarqube-opts + +extraConfig: + secrets: [] + configmaps: [] + +# account: +# adminPassword: admin +# currentAdminPassword: admin +# curlContainerImage: curlimages/curl:latest + +terminationGracePeriodSeconds: 60 + +# Big Bang Additions +hostname: bigbang.dev +istio: + enabled: true diff --git a/deployment/integrations/istio/kustomization.yaml b/deployment/integrations/istio/kustomization.yaml deleted file mode 100644 index aec7939c32a00112a9d55b94e1be2b11c9dd0ddb..0000000000000000000000000000000000000000 --- a/deployment/integrations/istio/kustomization.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1alpha1 -kind: Component - -resources: - - virtual-service.yaml diff --git a/deployment/integrations/istio/virtual-service.yaml b/deployment/integrations/istio/virtual-service.yaml deleted file mode 100644 index efbcc4a39b091ef530ccde5c3c3938455af2bae9..0000000000000000000000000000000000000000 --- a/deployment/integrations/istio/virtual-service.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: networking.istio.io/v1alpha3 -kind: VirtualService -metadata: - name: sonarqube -spec: - hosts: - - "sonarqube.dev.dsop.io" - gateways: - - istio-ingressgateway.istio-system.svc.cluster.local - http: - - match: - - uri: - prefix: / - route: - - destination: - host: sonarqube.sonarqube.svc.cluster.local - port: - number: 9000 diff --git a/deployment/integrations/rds/db-provisioner.yaml b/deployment/integrations/rds/db-provisioner.yaml deleted file mode 100644 index 396180fbcfbdb48d398e56e06533b8c5c29e9c95..0000000000000000000000000000000000000000 --- a/deployment/integrations/rds/db-provisioner.yaml +++ /dev/null @@ -1,32 +0,0 @@ -apiVersion: batch/v1 -kind: Job -metadata: - name: ensure-sonarqube-rds-db - annotations: - argocd.argoproj.io/hook: Sync - argocd.argoproj.io/hook-delete-policy: HookSucceeded -spec: - template: - metadata: - name: ensure-sonarqube-rds-db - annotations: - sidecar.istio.io/inject: 'false' - spec: - containers: - - name: psql - image: "bitnami/postgresql" - command: - - /bin/bash - - -exc - - | - psql -tc "SELECT 1 FROM pg_database WHERE datname = '$DB_NAME'" | grep -q 1 || psql -c "CREATE DATABASE $DB_NAME" - psql -tc "SELECT 1 FROM pg_roles WHERE rolname = '$APP_DB_USER'" | grep -q 1 && psql -c "ALTER USER $APP_DB_USER WITH PASSWORD '$APP_DB_PASSWORD'; GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $APP_DB_USER;" | grep -q GRANT || psql -c "CREATE USER $APP_DB_USER WITH PASSWORD '$APP_DB_PASSWORD'; GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $APP_DB_USER;" - env: - - name: DB_NAME - value: sonarqube - envFrom: - - secretRef: - name: db-credentials - - secretRef: - name: app-db-credentials - restartPolicy: OnFailure \ No newline at end of file diff --git a/deployment/integrations/rds/kustomization.yaml b/deployment/integrations/rds/kustomization.yaml deleted file mode 100644 index d61c9bd29f5ff5f90a7eb51622da1d65a1b151fa..0000000000000000000000000000000000000000 --- a/deployment/integrations/rds/kustomization.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1alpha1 -kind: Component - -resources: - - db-provisioner.yaml -images: - - name: bitnami/postgresql - newName: registry.dsop.io/platform-one/apps/sonarqube/postgres12-ib - newTag: 12.3-ib \ No newline at end of file diff --git a/deployment/manifests/all.yaml b/deployment/manifests/all.yaml deleted file mode 100644 index bb7351c3c7f0bfce2eb144c71d8cdc58c5450b62..0000000000000000000000000000000000000000 --- a/deployment/manifests/all.yaml +++ /dev/null @@ -1,159 +0,0 @@ ---- -# Source: sonarqube/templates/copy-plugins.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: sonarqube-copy-plugins -data: - copy_plugins.sh: |- - #!/bin/bash - exec /opt/sonarqube/bin/run.sh ---- -# Source: sonarqube/templates/install-plugins.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: sonarqube-install-plugins -data: - install_plugins.sh: |- - cd /opt/sonarqube/extensions/plugins/tmp ---- -# Source: sonarqube/templates/postgres-config.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: sonarqube-postgres-config -data: - SONARQUBE_JDBC_USERNAME: "sonarUser" - SONARQUBE_JDBC_URL: "jdbc:postgresql://db.admin.dsop.io:5432/sonarDB" ---- -# Source: sonarqube/templates/pvc.yaml -kind: PersistentVolumeClaim -apiVersion: v1 -metadata: - name: sonarqube -spec: - accessModes: - - "ReadWriteOnce" - resources: - requests: - storage: "10Gi" ---- -# Source: sonarqube/templates/service.yaml -apiVersion: v1 -kind: Service -metadata: - name: sonarqube -spec: - type: ClusterIP - ports: - - port: 9000 - targetPort: http - protocol: TCP - name: http ---- -# Source: sonarqube/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: sonarqube -spec: - # WARNING: One day clustering will be a thing, today is not that day $$$ - strategy: - type: Recreate - replicas: 1 - template: - spec: - securityContext: - fsGroup: 999 - containers: - - name: sonarqube - image: registry.dsop.io/platform-one/apps/sonarqube:8.4-0.1.2 - imagePullPolicy: IfNotPresent - ports: - - name: http - containerPort: 9000 - protocol: TCP - env: - - name: SONARQUBE_WEB_JVM_OPTS - value: "" - - name: SONARQUBE_JDBC_USERNAME - valueFrom: - secretKeyRef: - name: app-db-credentials - key: APP_DB_USER - - name: SONARQUBE_JDBC_PASSWORD - valueFrom: - secretKeyRef: - name: app-db-credentials - key: APP_DB_PASSWORD - - name: SONARQUBE_JDBC_URL - valueFrom: - secretKeyRef: - name: app-db-credentials - key: APP_DB_JDBC_URL - envFrom: - - configMapRef: - name: sonarqube-postgres-config - livenessProbe: - httpGet: - path: /sessions/new - port: http - initialDelaySeconds: 60 - periodSeconds: 30 - readinessProbe: - httpGet: - path: /sessions/new - port: http - initialDelaySeconds: 60 - periodSeconds: 30 - failureThreshold: 6 - volumeMounts: - - mountPath: /opt/sonarqube/conf/ - name: config - - mountPath: /opt/sonarqube/data - name: sonarqube - subPath: data - - mountPath: /opt/sonarqube/extensions/plugins/tmp - name: sonarqube - subPath: tmp - - mountPath: /opt/sonarqube/extensions/downloads - name: sonarqube - subPath: downloads - - mountPath: /opt/sonarqube/temp - name: sonarqube - subPath: temp - - mountPath: /opt/sonarqube/logs - name: sonarqube - subPath: logs - - mountPath: /tmp - name: tmp-dir - - name: copy-plugins - mountPath: /tmp/scripts - resources: - {} - volumes: - - name: config - configMap: - name: sonarqube-properties - items: - - key: sonar.properties - path: sonar.properties - - name: install-plugins - configMap: - name: sonarqube-install-plugins - items: - - key: install_plugins.sh - path: install_plugins.sh - - name: copy-plugins - configMap: - name: sonarqube-copy-plugins - defaultMode: 0755 - items: - - key: copy_plugins.sh - path: copy_plugins.sh - - name: sonarqube - persistentVolumeClaim: - claimName: sonarqube - - name : tmp-dir - emptyDir: {} diff --git a/deployment/manifests/kustomization.yaml b/deployment/manifests/kustomization.yaml deleted file mode 100755 index 70d89ee6836b197f9889d8c946243f786aa33698..0000000000000000000000000000000000000000 --- a/deployment/manifests/kustomization.yaml +++ /dev/null @@ -1,21 +0,0 @@ -namespace: sonarqube - -commonLabels: - app: sonarqube - -resources: - - namespace.yaml - - all.yaml - -configMapGenerator: - - name: sonarqube-properties - namespace: sonarqube - files: - - sonar.properties -images: - - name: registry.dsop.io/platform-one/apps/sonarqube:8.4-0.1.0 - newName: registry.dsop.io/platform-one/apps/sonarqube/sonarqube-ib - newTag: 8.3-community-ib-bb - - - diff --git a/deployment/manifests/namespace.yaml b/deployment/manifests/namespace.yaml deleted file mode 100755 index f18e1e9bc00f6a0ebbe11c091b5558877e230447..0000000000000000000000000000000000000000 --- a/deployment/manifests/namespace.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: sonarqube diff --git a/deployment/manifests/sonar.properties b/deployment/manifests/sonar.properties deleted file mode 100644 index ea8ed52de686aa98b17fa27ea26f67df70401844..0000000000000000000000000000000000000000 --- a/deployment/manifests/sonar.properties +++ /dev/null @@ -1,2 +0,0 @@ -sonar.es.bootstrap.checks.disable=true -sonar.forceAuthentication=true diff --git a/deployment/manifests/values.yaml b/deployment/manifests/values.yaml deleted file mode 100644 index 098a30a51017f14a653652fd4915cf7bf3d61ba4..0000000000000000000000000000000000000000 --- a/deployment/manifests/values.yaml +++ /dev/null @@ -1,21 +0,0 @@ -elasticsearch: - configureNode: false - bootstrapChecks: false - -ingress: - enabled: false - -persistence: - enabled: true - -postgresql: - enabled: false - - existingSecret: db-credentials - postgresqlServer: db.admin.dsop.io - postgresqlDatabase: sonarDB - - # plugins: - # - https://mattsmom.jar - -enableTests: false diff --git a/docs/Keycloak.md b/docs/Keycloak.md index d24d1906029145fbbe65d1c7f12d97c9a6f21c9c..5ec8cdd582162eaf42692fbcb1ced8dea3c3c8b5 100644 --- a/docs/Keycloak.md +++ b/docs/Keycloak.md @@ -1,4 +1,78 @@ -# Keycloak integration for Sonarqube +# SAML Keycloak integration for Sonarqube +[sonarqube docs](https://docs.sonarqube.org/latest/instance-administration/delegated-auth/#header-4) +## In the Keycloak server, create a new SAML client +Create a new client + +1. "Client ID" is something like "sonarqube" +2. "Client Protocol" must be set to "saml" +3. "Client SAML Endpoint" can be left empty + +Configure the new client + +1. in Settings + 1. Set"Client Signature Required" to OFF + 2. Set "Valid Redirect URIs" to "/oauth2/callback/*, E.G https://sonarqube.mycompany.com/oauth2/callback/saml +2. in Client Scopes > Default Client Scopes , remove "role_list" from "Assigned Default Client Scopes" (to prevent the error com.onelogin.saml2.exception.ValidationError: Found an Attribute element with duplicated Name during authentication) +3. In Mappers create a mapper for each user attribute (Note that values provided below for Name, SAML Attribute Name, Role Attribute Name are only example values): + 1. Create a mapper for the login: + 2. Name: Login + 3. Mapper Type: User Property + 4. Property: Username (Note that the login should not contain any special characters other than .-_@ to meet SonarQube restrictions.) + 5. SAML Attribute Name: login + 6. Create a mapper for the name: + 7. Name: Name + 8. Mapper Type: User Property + 9. User Attribute: Username (It can also be another attribute you would previously have specified for the users) + 10. SAML Attribute Name: name + 11. (Optional) Create a mapper for the email: + 12. Name: Email + 13. Mapper Type: User Property + 14. Property: Email + 15. SAML Attribute Name: email + 16. (Optional) Create a mapper for the groups (If you rely on a list of roles defined in "Roles" of the Realm (not in "Roles" of the client)): + 17. Name: Groups + 18. Mapper Type: Role list + 19. Role Attribute Name: groups + 20. Single Role Attribute: ON + 21. If you rely on a list of groups defined in "Groups": + 22. Name: Groups + 23. Mapper Type: Group list + 24. Role Attribute Name: groups + 25. Single Role Attribute: ON + 26. Full Group Path: OFF + +## In SonarQube, Configure SAML authentication +Go to Administration > Configuration > General Settings > Security > SAML +* Enabled should be set to true +* Application ID is the value of the "Client ID" you set in Keycloak (for example "sonarqube") +* Provider ID is the value of the "EntityDescriptor" > "entityID" attribute in the XML configuration file (for example "http://keycloak:8080/auth/realms/sonarqube" where sonarqube is the name of the realm) +* SAML login url is the value of "SingleSignOnService" > "Location" attribute in the XML configuration file (for example "http://keycloak:8080/auth/realms/sonarqube/protocol/saml") +* Provider certificate is the value you get from Reaml Settings -> Keys -> click on the Certificate button +* SAML user login attribute is the value set in the login mapper in "SAML Attribute Name" +* SAML user name attribute is the value set in the name mapper in "SAML Attribute Name" +* (Optional) SAML user email attribute is the value set in the email mapper in "SAML Attribute Name" +* (Optional) SAML group attribute is the value set in the groups mapper in "Role/Group Attribute Name" +In the login form, the new button "Log in with SAML" allows users to connect with their SAML account. + +## Helm Values Config example: +``` +sonarProperties: + sonar.forceAuthentication: true +# SAML SSO config + sonar.core.serverBaseURL: https://sonarqube.bigbang.dev + sonar.auth.saml.enabled: true + sonar.auth.saml.applicationId: platform1_a8604cc9-f5e9-4656-802d-d05624370245_bb8-saml-sonarqube + sonar.auth.saml.providerName: P1 SSO + sonar.auth.saml.providerId: https://login.dsop.io/auth/realms/baby-yoda + sonar.auth.saml.loginUrl: https://login.dsop.io/auth/realms/baby-yoda/protocol/saml + sonar.auth.saml.certificate.secured: MILicoTCCAYkCBgFyLIEqUjaNbg... + sonar.auth.saml.user.login: login + sonar.auth.saml.user.name: name + # sonar.auth.saml.user.email: email + # sonar.auth.saml.group.name: group +``` + +# OIDC Keycloak integration for Sonarqube 1. Login to Sonarqube with default admin credentials username: admin password: admin 2. In Adminstration->General @@ -34,4 +108,3 @@ 7. Go to Administration->Security->Users and add username created above to sonar-admin group 8. Go to Administration->Security->Users and delete admin user 9. Logout of Sonarqune and login with username and password created in keycloak - diff --git a/tests/cy-run.sh b/tests/cy-run.sh new file mode 100644 index 0000000000000000000000000000000000000000..2df7a77796b123ada7ac4d0d357ac452e4fedebc --- /dev/null +++ b/tests/cy-run.sh @@ -0,0 +1,16 @@ + +#!/usr/bin/env bash +echo "Running Cypress e2e tests headlessly without copying files" + +# explanation of the "docker run" command line arguments +# +# -it = interactive terminal +# -v $PWD:/e2e = map current folder to /e2e inside the container +# -w /e2e = set working directy to /e2e +# $@ = pass any arguments to this script to the Cypress command +# like "./cy-run.sh --record" +# +# Docker image "cypress/included:3.2.0" has its entrypoint +# set to "cypress run" by default + +docker run -it -v $PWD:/e2e -w /e2e cypress/included:5.0.0 $@ diff --git a/tests/cypress.json b/tests/cypress.json new file mode 100644 index 0000000000000000000000000000000000000000..9408b4cb5d49be31017d2a390fb6b613e22d9456 --- /dev/null +++ b/tests/cypress.json @@ -0,0 +1,11 @@ +{ + + "pluginsFile": false, + "supportFile": false, + "fixturesFolder": false, + "env": { + "sonarqube_url": "sonarqube.bigbang.dev", + "sonarqube_password": "admin", + "sonarqube_user": "admin" + } +} diff --git a/tests/cypress/integration/sonarqube-health.spec.js b/tests/cypress/integration/sonarqube-health.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..7e1c62ed9e84fdedb6a50bf17931ba94637d9095 --- /dev/null +++ b/tests/cypress/integration/sonarqube-health.spec.js @@ -0,0 +1,10 @@ +// needs to be fixed +describe('Basic Sonarqube', function() { + it('Check Sonarqube is accessible', function() { + cy.visit(Cypress.env('sonarqube_url')) + cy.get('input[name="login"]').type(Cypress.env('sonarqube_user')) + cy.get('input[name="password"]').type(Cypress.env('sonarqube_password')) + cy.contains("Log in").click() + cy.contains('Update your password') + }) +}) diff --git a/tests/main-test-gateway.yaml b/tests/main-test-gateway.yaml new file mode 100644 index 0000000000000000000000000000000000000000..298b582f3b3c8884a1c84dc77ab4846f8a63f531 --- /dev/null +++ b/tests/main-test-gateway.yaml @@ -0,0 +1,36 @@ +apiVersion: networking.istio.io/v1beta1 +kind: Gateway +metadata: + annotations: + meta.helm.sh/release-name: istio-system-istio + meta.helm.sh/release-namespace: istio-system + creationTimestamp: "2020-12-08T01:19:38Z" + generation: 1 + labels: + app.kubernetes.io/managed-by: Helm + name: main + namespace: istio-system + resourceVersion: "1661" + selfLink: /apis/networking.istio.io/v1beta1/namespaces/istio-system/gateways/main + uid: 9cfaa8c6-744a-49b3-abc0-b3960153c9b2 +spec: + selector: + istio: ingressgateway + servers: + - hosts: + - '*' + port: + name: http + number: 80 + protocol: HTTP + tls: + httpsRedirect: true + - hosts: + - '*.bigbang.dev' + port: + name: https + number: 443 + protocol: HTTPS + tls: + credentialName: wildcard-cert + mode: SIMPLE diff --git a/tests/test-values.yml b/tests/test-values.yml new file mode 100644 index 0000000000000000000000000000000000000000..0a6dca533983fabc4d6b2a6d87c4ccb2db6b1311 --- /dev/null +++ b/tests/test-values.yml @@ -0,0 +1,355 @@ +# Default values for sonarqube. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +replicaCount: 1 + + # This will use the default deployment strategy unless it is overriden +deploymentStrategy: {} +# Uncomment this to scheduler pods on priority +# priorityClassName: "high-priority" + +## Use an alternate scheduler, e.g. "stork". +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +# schedulerName: + +## Is this deployment for OpenShift? If so, we help with SCCs +OpenShift: + enabled: false + createSCC: true + +image: + repository: registry1.dso.mil/ironbank/sonarsource/sonarqube/sonarqube8-community + tag: 8.6-community + pullPolicy: IfNotPresent + # If using a private repository, the name of the imagePullSecret to use + pullSecret: private-registry-mil + +# Set security context for sonarqube pod +securityContext: + fsGroup: 1000 + +# Set security context for sonarqube container +containerSecurityContext: + # Sonarqube dockerfile creates sonarqube user as UID and GID 1000 + runAsUser: 1000 + +# Settings to configure elasticsearch host requirements +elasticsearch: + # DEPRECATED: Use initSysctl.enabled instead + configureNode: true + bootstrapChecks: true + +service: + type: ClusterIP + externalPort: 9000 + internalPort: 9000 + labels: + annotations: {} + # May be used in example for internal load balancing in GCP: + # cloud.google.com/load-balancer-type: Internal + # loadBalancerSourceRanges: + # - 0.0.0.0/0 + # loadBalancerIP: 1.2.3.4 +ingress: + enabled: false + # Used to create an Ingress record. + hosts: + - name: sonar.example.com + # Different clouds or configurations might need /* as the default path + path: / + # For additional control over serviceName and servicePort + # serviceName: someService + # servicePort: somePort + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + # This property allows for reports up to a certain size to be uploaded to SonarQube + # nginx.ingress.kubernetes.io/proxy-body-size: "8m" + +# Additional labels for Ingress manifest file + # labels: + # traffic-type: external + # traffic-type: internal + tls: [] + # Secrets must be manually created in the namespace. + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +# Affinity for pod assignment +# Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +affinity: {} + +# Tolerations for pod assignment +# Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +tolerations: [] + +# Node labels for pod assignment +# Ref: https://kubernetes.io/docs/user-guide/node-selection/ +nodeSelector: {} + +# hostAliases allows the modification of the hosts file inside a container +hostAliases: [] +# - ip: "192.168.1.10" +# hostnames: +# - "example.com" +# - "www.example.com" + +readinessProbe: + initialDelaySeconds: 60 + periodSeconds: 30 + failureThreshold: 6 + # If an ingress *path* other than the root (/) is defined, it should be reflected here + # A trailing "/" must be included + sonarWebContext: / + # sonarWebContext: /sonarqube/ +livenessProbe: + initialDelaySeconds: 60 + periodSeconds: 30 + # If an ingress *path* other than the root (/) is defined, it should be reflected here + # A trailing "/" must be included + sonarWebContext: / + # sonarWebContext: /sonarqube/ + # If an ingress *path* is defined, it should be reflected here + # sonar.web.context: /sonarqube + +initContainers: + # image: busybox:1.32 + # We allow the init containers to have a separate security context declaration because + # the initContainer may not require the same as SonarQube. + # securityContext: {} + # We allow the init containers to have a separate resources declaration because + # the initContainer does not take as much resources. + resources: {} + +## Provide a secret containing one or more certificate files in the keys that will be added to cacerts +## The cacerts file will be set via SONARQUBE_WEB_JVM_OPTS and SONAR_CE_JAVAOPTS +## +# caCerts: + # image: adoptopenjdk/openjdk11:alpine + # secret: my-secret + +initSysctl: + enabled: true + vmMaxMapCount: 524288 + fsFileMax: 131072 + nofile: 131072 + nproc: 8192 + # image: busybox:1.32 + securityContext: + privileged: true + # resources: {} + +# List of plugins to install. +# For example: +# plugins: +# install: +# - "https://github.com/AmadeusITGroup/sonar-stash/releases/download/1.3.0/sonar-stash-plugin-1.3.0.jar" +# - "https://github.com/SonarSource/sonar-ldap/releases/download/2.2-RC3/sonar-ldap-plugin-2.2.0.601.jar" +plugins: + install: [] + lib: [] + + # For use behind a corporate proxy when downloading plugins + # httpProxy: "" + # httpsProxy: "" + # noProxy: "" + + # image: rjkernick/alpine-wget:latest + # resources: {} + + # .netrc secret file with a key "netrc" to use basic auth while downloading plugins + # netrcCreds: "" + +## Values to add to SONARQUBE_WEB_JVM_OPTS +## +# jvmOpts: "-Djava.net.preferIPv4Stack=true" +jvmOpts: "" + +## Environment variables to attach to the pods +## +# env: +# - name: VARIABLE +# value: my-value + +# Set annotations for pods +annotations: {} + +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 +persistence: + enabled: false + ## Set annotations on pvc + annotations: {} + + ## Specify an existing volume claim instead of creating a new one. + ## When using this option all following options like storageClass, accessMode and size are ignored. + # existingClaim: + + ## 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: + accessMode: ReadWriteOnce + size: 10Gi + + ## Specify extra volumes. Refer to ".spec.volumes" specification : https://kubernetes.io/fr/docs/concepts/storage/volumes/ + volumes: [] + ## Specify extra mounts. Refer to ".spec.containers.volumeMounts" specification : https://kubernetes.io/fr/docs/concepts/storage/volumes/ + mounts: [] + +# In case you want to specify different resources for emptyDir than {} +emptyDir: {} + # Example of resouces that might be used: + # medium: Memory + # sizeLimit: 16Mi + +# A custom sonar.properties file can be provided via dictionary. +# For example: +sonarProperties: + sonar.forceAuthentication: true +# SAML SSO config +# sonar.auth.saml.enabled: false +# sonar.core.serverBaseURL: https://sonarqube.bigbang.dev +# sonar.auth.saml.applicationId: platform1_a8604cc9-f5e9-4656-802d-d05624370245_bb8-saml-sonarqube +# sonar.auth.saml.providerName: P1 SSO +# sonar.auth.saml.providerId: https://login.dsop.io/auth/realms/baby-yoda +# sonar.auth.saml.loginUrl: https://login.dsop.io/auth/realms/baby-yoda/protocol/saml +# sonar.auth.saml.certificate.secured: MITCAYCBFyIEUjNBkqhkiG9w0BA.... +# sonar.auth.saml.user.login: login +# sonar.auth.saml.user.name: name +# sonar.auth.saml.user.email: email +# sonar.auth.saml.group.name: group + +# Additional sonar properties to load from a secret with a key "secret.properties" (must be a string) +# sonarSecretProperties: + +# Kubernetes secret that contains the encryption key for the sonarqube instance. +# The secret must contain the key 'sonar-secret.txt'. +# The 'sonar.secretKeyPath' property will be set automatically. +# sonarSecretKey: "settings-encryption-secret" + +## JDBC Database Type; by default postgresql. To use a different Database type, adjust +jdbcDatabaseType: postgresql + +## Override JDBC URL +# jdbcUrlOverride: "jdbc:postgresql://myPostgress/myDatabase;socketTimeout=1500" + +## Configuration values for postgresql dependency +## ref: https://github.com/kubernetes/charts/blob/master/stable/postgresql/README.md +postgresql: + # Enable to deploy the PostgreSQL chart + enabled: true + # To use an external PostgreSQL instance, set enabled to false and uncomment + # the line below: + # postgresqlServer: "" + # To use an external secret for the password for an external PostgreSQL + # instance, set enabled to false and provide the name of the secret on the + # line below: + # existingSecret: "" + postgresqlUsername: "sonarUser" + postgresqlPassword: "sonarPass" + postgresqlDatabase: "sonarDB" + # Specify the TCP port that PostgreSQL should use + service: + port: 5432 + resources: + limits: + cpu: 2 + memory: 2Gi + requests: + cpu: 100m + memory: 200Mi + persistence: + enabled: true + accessMode: ReadWriteOnce + size: 20Gi + storageClass: + securityContext: + # For standard Kubernetes deployment, set enabled=true + # If using OpenShift, enabled=false for restricted SCC and enabled=true for anyuid/nonroot SCC + enabled: true + # fsGroup and runAsUser specifications below are not applied if enabled=false. enabled=false is the required setting for OpenShift "restricted SCC" to work successfully. + # postgresql dockerfile sets user as 1001 + fsGroup: 1001 + runAsUser: 1001 + volumePermissions: + # For standard Kubernetes deployment, set enabled=false + # For OpenShift, set enabled=true and ensure to set volumepermissions.securitycontext.runAsUser below. + enabled: false + # if using restricted SCC set runAsUser: "auto" and if running under anyuid/nonroot SCC - runAsUser needs to match runAsUser above + securityContext: + runAsUser: 0 + shmVolume: + chmod: + enabled: false + serviceAccount: + ## If enabled = true, and name is not set, postgreSQL will create a serviceAccount + enabled: false +# name: + +# Additional labels to add to the pods: +# podLabels: +# key: value +podLabels: {} +# For compatibility with 8.0 replace by "/opt/sq" +# For compatibility with 8.2, leave the default. They changed it back to /opt/sonarqube +sonarqubeFolder: /opt/sonarqube + +tests: + enabled: true + # image: bitnami/minideb-extras + +serviceAccount: + create: false + # name: + ## Annotations for the Service Account + annotations: {} + +# extraConfig is used to load Environment Variables from Secrets and ConfigMaps +# which may have been written by other tools, such as external orchestrators. +# +# These Secrets/ConfigMaps are expected to contain Key/Value pairs, such as: +# +# apiVersion: v1 +# kind: ConfigMap +# metadata: +# name: external-sonarqube-opts +# data: +# SONARQUBE_JDBC_USERNAME: foo +# SONARQUBE_JDBC_URL: jdbc:postgresql://db.example.com:5432/sonar +# +# These vars can then be injected into the environment by uncommenting the following: +# +# extraConfig: +# configmaps: +# - external-sonarqube-opts + +extraConfig: + secrets: [] + configmaps: [] + +# account: +# adminPassword: admin +# currentAdminPassword: admin +# curlContainerImage: curlimages/curl:latest + +terminationGracePeriodSeconds: 60 + +# Big Bang Additions +hostname: bigbang.dev +istio: + enabled: true